[K2/N] KT-56030: Support Objective-C overloading by param names only
Merge-request: KT-MR-8901 Merged-by: Vladimir Sukharev <Vladimir.Sukharev@jetbrains.com>
This commit is contained in:
committed by
Space Team
parent
c957a0b43b
commit
b9633375b4
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
|||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.common.prepareJsSessions
|
import org.jetbrains.kotlin.cli.common.prepareJsSessions
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
|
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
|
||||||
@@ -28,6 +27,7 @@ import org.jetbrains.kotlin.fir.FirSession
|
|||||||
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
|
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
|
||||||
import org.jetbrains.kotlin.fir.backend.Fir2IrVisibilityConverter
|
import org.jetbrains.kotlin.fir.backend.Fir2IrVisibilityConverter
|
||||||
import org.jetbrains.kotlin.fir.backend.extractFirDeclarations
|
import org.jetbrains.kotlin.fir.backend.extractFirDeclarations
|
||||||
|
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||||
@@ -133,6 +133,7 @@ fun transformFirToIr(
|
|||||||
linkViaSignatures = false,
|
linkViaSignatures = false,
|
||||||
signatureComposerCreator = null,
|
signatureComposerCreator = null,
|
||||||
irMangler = JsManglerIr,
|
irMangler = JsManglerIr,
|
||||||
|
firManglerCreator = { FirJvmKotlinMangler() },
|
||||||
visibilityConverter = Fir2IrVisibilityConverter.Default,
|
visibilityConverter = Fir2IrVisibilityConverter.Default,
|
||||||
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
|
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
|
||||||
diagnosticReporter = diagnosticsReporter,
|
diagnosticReporter = diagnosticsReporter,
|
||||||
|
|||||||
@@ -9,10 +9,7 @@ import org.jetbrains.kotlin.KtSourceFile
|
|||||||
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.GroupedKtSources
|
import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.GroupedKtSources
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.fir.DependencyListForCliModule
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.FirModuleData
|
|
||||||
import org.jetbrains.kotlin.fir.FirModuleDataImpl
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
|
||||||
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
|
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||||
@@ -160,6 +157,7 @@ fun <F> prepareNativeSessions(
|
|||||||
extensionRegistrars: List<FirExtensionRegistrar>,
|
extensionRegistrars: List<FirExtensionRegistrar>,
|
||||||
isCommonSource: (F) -> Boolean,
|
isCommonSource: (F) -> Boolean,
|
||||||
fileBelongsToModule: (F, String) -> Boolean,
|
fileBelongsToModule: (F, String) -> Boolean,
|
||||||
|
registerExtraComponents: ((FirSession) -> Unit) = {},
|
||||||
): List<SessionWithSources<F>> {
|
): List<SessionWithSources<F>> {
|
||||||
return prepareSessions(
|
return prepareSessions(
|
||||||
files, configuration, rootModuleName, NativePlatforms.unspecifiedNativePlatform, NativePlatformAnalyzerServices,
|
files, configuration, rootModuleName, NativePlatforms.unspecifiedNativePlatform, NativePlatformAnalyzerServices,
|
||||||
@@ -171,7 +169,7 @@ fun <F> prepareNativeSessions(
|
|||||||
libraryList.moduleDataProvider,
|
libraryList.moduleDataProvider,
|
||||||
extensionRegistrars,
|
extensionRegistrars,
|
||||||
configuration.languageVersionSettings,
|
configuration.languageVersionSettings,
|
||||||
registerExtraComponents = {},
|
registerExtraComponents,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { _, moduleData, sessionProvider, sessionConfigurator ->
|
) { _, moduleData, sessionProvider, sessionConfigurator ->
|
||||||
@@ -181,6 +179,7 @@ fun <F> prepareNativeSessions(
|
|||||||
extensionRegistrars,
|
extensionRegistrars,
|
||||||
configuration.languageVersionSettings,
|
configuration.languageVersionSettings,
|
||||||
sessionConfigurator,
|
sessionConfigurator,
|
||||||
|
registerExtraComponents,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.signaturer.FirMangler
|
||||||
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler
|
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler
|
||||||
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
|
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
@@ -55,6 +56,7 @@ fun FirResult.convertToIrAndActualizeForJvm(
|
|||||||
linkViaSignatures = linkViaSignatures,
|
linkViaSignatures = linkViaSignatures,
|
||||||
signatureComposerCreator = { JvmIdSignatureDescriptor(JvmDescriptorMangler(null)) },
|
signatureComposerCreator = { JvmIdSignatureDescriptor(JvmDescriptorMangler(null)) },
|
||||||
irMangler = JvmIrMangler,
|
irMangler = JvmIrMangler,
|
||||||
|
firManglerCreator = { FirJvmKotlinMangler() },
|
||||||
visibilityConverter = FirJvmVisibilityConverter,
|
visibilityConverter = FirJvmVisibilityConverter,
|
||||||
diagnosticReporter = diagnosticReporter,
|
diagnosticReporter = diagnosticReporter,
|
||||||
languageVersionSettings = languageVersionSettings,
|
languageVersionSettings = languageVersionSettings,
|
||||||
@@ -67,6 +69,7 @@ fun FirResult.convertToIrAndActualize(
|
|||||||
linkViaSignatures: Boolean,
|
linkViaSignatures: Boolean,
|
||||||
signatureComposerCreator: (() -> IdSignatureComposer)?,
|
signatureComposerCreator: (() -> IdSignatureComposer)?,
|
||||||
irMangler: KotlinMangler.IrMangler,
|
irMangler: KotlinMangler.IrMangler,
|
||||||
|
firManglerCreator: () -> FirMangler,
|
||||||
visibilityConverter: Fir2IrVisibilityConverter,
|
visibilityConverter: Fir2IrVisibilityConverter,
|
||||||
kotlinBuiltIns: KotlinBuiltIns,
|
kotlinBuiltIns: KotlinBuiltIns,
|
||||||
diagnosticReporter: DiagnosticReporter,
|
diagnosticReporter: DiagnosticReporter,
|
||||||
@@ -79,7 +82,7 @@ fun FirResult.convertToIrAndActualize(
|
|||||||
val commonMemberStorage = Fir2IrCommonMemberStorage(
|
val commonMemberStorage = Fir2IrCommonMemberStorage(
|
||||||
generateSignatures = linkViaSignatures,
|
generateSignatures = linkViaSignatures,
|
||||||
signatureComposerCreator = signatureComposerCreator,
|
signatureComposerCreator = signatureComposerCreator,
|
||||||
manglerCreator = { FirJvmKotlinMangler() } // TODO: replace with potentially simpler version for other backends.
|
manglerCreator = firManglerCreator
|
||||||
)
|
)
|
||||||
|
|
||||||
when (outputs.size) {
|
when (outputs.size) {
|
||||||
@@ -94,7 +97,9 @@ fun FirResult.convertToIrAndActualize(
|
|||||||
irMangler,
|
irMangler,
|
||||||
visibilityConverter,
|
visibilityConverter,
|
||||||
kotlinBuiltIns,
|
kotlinBuiltIns,
|
||||||
)
|
).also { result ->
|
||||||
|
fir2IrResultPostCompute(result)
|
||||||
|
}
|
||||||
actualizationResult = null
|
actualizationResult = null
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.impl.FirTypeResolverImpl
|
|||||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirDummyCompilerLazyDeclarationResolver
|
import org.jetbrains.kotlin.fir.resolve.transformers.FirDummyCompilerLazyDeclarationResolver
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.PlatformSupertypeUpdater
|
import org.jetbrains.kotlin.fir.resolve.transformers.PlatformSupertypeUpdater
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClassIndex
|
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClassIndex
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideService
|
import org.jetbrains.kotlin.fir.scopes.FirOverrideService
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||||
import org.jetbrains.kotlin.fir.scopes.PlatformSpecificOverridabilityRules
|
import org.jetbrains.kotlin.fir.scopes.PlatformSpecificOverridabilityRules
|
||||||
@@ -70,6 +71,8 @@ fun FirSession.registerCommonComponents(languageVersionSettings: LanguageVersion
|
|||||||
register(FirSamConstructorStorage::class, FirSamConstructorStorage(this))
|
register(FirSamConstructorStorage::class, FirSamConstructorStorage(this))
|
||||||
register(FirOverrideService::class, FirOverrideService(this))
|
register(FirOverrideService::class, FirOverrideService(this))
|
||||||
register(FirDynamicMembersStorage::class, FirDynamicMembersStorage(this))
|
register(FirDynamicMembersStorage::class, FirDynamicMembersStorage(this))
|
||||||
|
register(FirEnumEntriesSupport::class, FirEnumEntriesSupport(this))
|
||||||
|
register(FirOverrideChecker::class, FirStandardOverrideChecker(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(SessionConfiguration::class)
|
@OptIn(SessionConfiguration::class)
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.resolve.providers.impl.FirBuiltinSymbolProvider
|
|||||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirExtensionSyntheticFunctionInterfaceProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirExtensionSyntheticFunctionInterfaceProvider
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirEnumEntriesSupport
|
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -98,6 +97,5 @@ object FirJsSessionFactory : FirAbstractSessionFactory() {
|
|||||||
register(ConeCallConflictResolverFactory::class, JsCallConflictResolverFactory)
|
register(ConeCallConflictResolverFactory::class, JsCallConflictResolverFactory)
|
||||||
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
|
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
|
||||||
register(FirOverridesBackwardCompatibilityHelper::class, FirOverridesBackwardCompatibilityHelper.Default())
|
register(FirOverridesBackwardCompatibilityHelper::class, FirOverridesBackwardCompatibilityHelper.Default())
|
||||||
register(FirEnumEntriesSupport::class, FirEnumEntriesSupport(this))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -37,7 +37,9 @@ object FirNativeSessionFactory : FirAbstractSessionFactory() {
|
|||||||
moduleDataProvider,
|
moduleDataProvider,
|
||||||
languageVersionSettings,
|
languageVersionSettings,
|
||||||
extensionRegistrars,
|
extensionRegistrars,
|
||||||
registerExtraComponents,
|
registerExtraComponents = { session ->
|
||||||
|
registerExtraComponents(session)
|
||||||
|
},
|
||||||
createKotlinScopeProvider = { FirKotlinScopeProvider { _, declaredMemberScope, _, _, _ -> declaredMemberScope } },
|
createKotlinScopeProvider = { FirKotlinScopeProvider { _, declaredMemberScope, _, _, _ -> declaredMemberScope } },
|
||||||
createProviders = { session, builtinsModuleData, kotlinScopeProvider ->
|
createProviders = { session, builtinsModuleData, kotlinScopeProvider ->
|
||||||
val forwardDeclarationsModuleData = BinaryModuleData.createDependencyModuleData(
|
val forwardDeclarationsModuleData = BinaryModuleData.createDependencyModuleData(
|
||||||
|
|||||||
-2
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
|||||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
|
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirEnumEntriesSupport
|
|
||||||
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
|
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
|
||||||
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
|
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
|
||||||
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
|
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
|
||||||
@@ -128,6 +127,5 @@ object FirSessionFactoryHelper {
|
|||||||
register(ConeCallConflictResolverFactory::class, DefaultCallConflictResolverFactory)
|
register(ConeCallConflictResolverFactory::class, DefaultCallConflictResolverFactory)
|
||||||
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
|
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
|
||||||
register(FirOverridesBackwardCompatibilityHelper::class, FirOverridesBackwardCompatibilityHelper.Default())
|
register(FirOverridesBackwardCompatibilityHelper::class, FirOverridesBackwardCompatibilityHelper.Default())
|
||||||
register(FirEnumEntriesSupport::class, FirEnumEntriesSupport(this))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-18
@@ -7,27 +7,11 @@ package org.jetbrains.kotlin.fir.backend.jvm
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.*
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.*
|
||||||
import org.jetbrains.kotlin.fir.NoMutableState
|
import org.jetbrains.kotlin.fir.NoMutableState
|
||||||
|
import org.jetbrains.kotlin.fir.backend.FirBasedKotlinMangler
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.signaturer.FirMangler
|
|
||||||
|
|
||||||
@NoMutableState
|
@NoMutableState
|
||||||
class FirJvmKotlinMangler : AbstractKotlinMangler<FirDeclaration>(), FirMangler {
|
class FirJvmKotlinMangler : FirBasedKotlinMangler() {
|
||||||
|
|
||||||
override fun FirDeclaration.mangleString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.FULL, compatibleMode).computeMangle(this)
|
|
||||||
|
|
||||||
override fun FirDeclaration.signatureString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.SIGNATURE, compatibleMode).computeMangle(this)
|
|
||||||
|
|
||||||
override fun FirDeclaration.fqnString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.FQNAME, compatibleMode).computeMangle(this)
|
|
||||||
|
|
||||||
override fun FirDeclaration.isExported(compatibleMode: Boolean): Boolean = true
|
|
||||||
|
|
||||||
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<FirDeclaration> {
|
|
||||||
return object : KotlinExportChecker<FirDeclaration> {
|
|
||||||
override fun check(declaration: FirDeclaration, type: SpecialDeclarationType): Boolean = true
|
|
||||||
|
|
||||||
override fun FirDeclaration.isPlatformSpecificExported(): Boolean = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): KotlinMangleComputer<FirDeclaration> {
|
override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): KotlinMangleComputer<FirDeclaration> {
|
||||||
return FirJvmMangleComputer(StringBuilder(256), mode)
|
return FirJvmMangleComputer(StringBuilder(256), mode)
|
||||||
|
|||||||
+11
-236
@@ -5,25 +5,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.backend.jvm
|
package org.jetbrains.kotlin.fir.backend.jvm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.*
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.backend.FirMangleComputer
|
||||||
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
|
||||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
|
||||||
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.signaturer.irName
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mangle computer that generates a mangled name for a Kotlin declaration represented by [FirDeclaration].
|
* A mangle computer that generates a mangled name for a Kotlin declaration represented by [FirDeclaration].
|
||||||
@@ -31,20 +23,8 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
|||||||
class FirJvmMangleComputer(
|
class FirJvmMangleComputer(
|
||||||
builder: StringBuilder,
|
builder: StringBuilder,
|
||||||
mode: MangleMode,
|
mode: MangleMode,
|
||||||
) : BaseKotlinMangleComputer<
|
) : FirMangleComputer(builder, mode) {
|
||||||
/*Declaration=*/FirDeclaration,
|
override val visitor = JvmVisitor()
|
||||||
/*Type=*/ConeKotlinType,
|
|
||||||
/*TypeParameter=*/ConeTypeParameterLookupTag,
|
|
||||||
/*ValueParameter=*/FirValueParameter,
|
|
||||||
/*TypeParameterContainer=*/FirMemberDeclaration,
|
|
||||||
/*FunctionDeclaration=*/FirFunction,
|
|
||||||
/*Session=*/FirSession,
|
|
||||||
>(builder, mode) {
|
|
||||||
|
|
||||||
override fun getTypeSystemContext(session: FirSession) = object : ConeInferenceContext {
|
|
||||||
override val session: FirSession
|
|
||||||
get() = session
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun FirFunction.platformSpecificSuffix(): String? =
|
override fun FirFunction.platformSpecificSuffix(): String? =
|
||||||
if (this is FirSimpleFunction && name.asString() == "main")
|
if (this is FirSimpleFunction && name.asString() == "main")
|
||||||
@@ -56,6 +36,7 @@ class FirJvmMangleComputer(
|
|||||||
override fun copy(newMode: MangleMode): FirJvmMangleComputer =
|
override fun copy(newMode: MangleMode): FirJvmMangleComputer =
|
||||||
FirJvmMangleComputer(builder, newMode)
|
FirJvmMangleComputer(builder, newMode)
|
||||||
|
|
||||||
|
// FIXME this implementation causes the mangler to deliver different result than IR mangler. Consider using base method instead
|
||||||
override fun FirDeclaration.visitParent() {
|
override fun FirDeclaration.visitParent() {
|
||||||
val (parentPackageFqName, parentClassId) = when (this) {
|
val (parentPackageFqName, parentClassId) = when (this) {
|
||||||
is FirCallableDeclaration -> this.containingClassLookupTag()?.classId?.let { it.packageFqName to it } ?: return
|
is FirCallableDeclaration -> this.containingClassLookupTag()?.classId?.let { it.packageFqName to it } ?: return
|
||||||
@@ -75,71 +56,7 @@ class FirJvmMangleComputer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun FirDeclaration.visit() {
|
// FIXME this implementation causes the mangler to deliver different result than IR mangler. Consider using base method instead
|
||||||
accept(Visitor(), null)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirFunction.mangleFunction(isCtor: Boolean, isStatic: Boolean, container: FirDeclaration) {
|
|
||||||
|
|
||||||
isRealExpect = isRealExpect || (this as? FirMemberDeclaration)?.isExpect == true
|
|
||||||
|
|
||||||
if (container is FirMemberDeclaration) {
|
|
||||||
typeParameterContainers.add(container)
|
|
||||||
}
|
|
||||||
visitParent()
|
|
||||||
|
|
||||||
builder.appendName(MangleConstant.FUNCTION_NAME_PREFIX)
|
|
||||||
|
|
||||||
platformSpecificFunctionName()?.let {
|
|
||||||
builder.append(it)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val name = this.irName
|
|
||||||
builder.append(name.asString())
|
|
||||||
|
|
||||||
platformSpecificSuffix()?.let {
|
|
||||||
builder.append(MangleConstant.PLATFORM_FUNCTION_MARKER)
|
|
||||||
builder.append(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
mangleSignature(isCtor, isStatic, container)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirFunction.mangleSignature(isCtor: Boolean, isStatic: Boolean, container: FirDeclaration) {
|
|
||||||
if (!mode.signature) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isStatic) {
|
|
||||||
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
|
|
||||||
}
|
|
||||||
|
|
||||||
contextReceivers.forEach {
|
|
||||||
builder.appendSignature(MangleConstant.CONTEXT_RECEIVER_PREFIX)
|
|
||||||
mangleType(builder, it.typeRef.coneType, moduleData.session)
|
|
||||||
}
|
|
||||||
|
|
||||||
val receiverType = receiverParameter?.typeRef ?: (this as? FirPropertyAccessor)?.propertySymbol?.fir?.receiverParameter?.typeRef
|
|
||||||
receiverType?.let {
|
|
||||||
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
|
|
||||||
mangleType(builder, it.coneType, moduleData.session)
|
|
||||||
}
|
|
||||||
|
|
||||||
valueParameters.collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
|
|
||||||
appendSignature(specialValueParamPrefix(it))
|
|
||||||
mangleValueParameter(this, it, moduleData.session)
|
|
||||||
}
|
|
||||||
(container as? FirTypeParametersOwner)?.typeParameters?.withIndex()?.toList().orEmpty()
|
|
||||||
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
|
|
||||||
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, moduleData.session)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isCtor && !returnTypeRef.isUnit && addReturnType()) {
|
|
||||||
mangleType(builder, returnTypeRef.coneType, moduleData.session)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getEffectiveParent(typeParameter: ConeTypeParameterLookupTag): FirMemberDeclaration = typeParameter.symbol.fir.run {
|
override fun getEffectiveParent(typeParameter: ConeTypeParameterLookupTag): FirMemberDeclaration = typeParameter.symbol.fir.run {
|
||||||
|
|
||||||
fun FirTypeParameter.sameAs(other: FirTypeParameter) =
|
fun FirTypeParameter.sameAs(other: FirTypeParameter) =
|
||||||
@@ -161,124 +78,7 @@ class FirJvmMangleComputer(
|
|||||||
throw IllegalStateException("Should not be here!")
|
throw IllegalStateException("Should not be here!")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renderDeclaration(declaration: FirDeclaration) = declaration.render()
|
protected inner class JvmVisitor : Visitor() {
|
||||||
|
|
||||||
override fun getTypeParameterName(typeParameter: ConeTypeParameterLookupTag) = typeParameter.name.asString()
|
|
||||||
|
|
||||||
override fun isVararg(valueParameter: FirValueParameter) = valueParameter.isVararg
|
|
||||||
|
|
||||||
override fun getValueParameterType(valueParameter: FirValueParameter) = valueParameter.returnTypeRef.coneType
|
|
||||||
|
|
||||||
override fun getIndexOfTypeParameter(typeParameter: ConeTypeParameterLookupTag, container: FirMemberDeclaration) =
|
|
||||||
container.typeParameters.indexOf(typeParameter.symbol.fir)
|
|
||||||
|
|
||||||
override fun mangleType(tBuilder: StringBuilder, type: ConeKotlinType, declarationSiteSession: FirSession) {
|
|
||||||
when (type) {
|
|
||||||
is ConeLookupTagBasedType -> {
|
|
||||||
when (val symbol = type.lookupTag.toSymbol(declarationSiteSession)) {
|
|
||||||
is FirTypeAliasSymbol -> {
|
|
||||||
mangleType(tBuilder, type.fullyExpandedType(declarationSiteSession), declarationSiteSession)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
is FirClassSymbol -> with(copy(MangleMode.FQNAME)) { symbol.fir.visit() }
|
|
||||||
is FirTypeParameterSymbol -> tBuilder.mangleTypeParameterReference(symbol.toLookupTag())
|
|
||||||
// This is performed for a case with invisible class-like symbol in fake override
|
|
||||||
null -> (type.lookupTag as? ConeClassLikeLookupTag)?.let {
|
|
||||||
tBuilder.append(it.classId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mangleTypeArguments(tBuilder, type, declarationSiteSession)
|
|
||||||
|
|
||||||
if (type.isMarkedNullable) {
|
|
||||||
tBuilder.appendSignature(MangleConstant.Q_MARK)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type.hasEnhancedNullability) {
|
|
||||||
tBuilder.appendSignature(MangleConstant.ENHANCED_NULLABILITY_MARK)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is ConeRawType -> {
|
|
||||||
mangleType(tBuilder, type.lowerBound, declarationSiteSession)
|
|
||||||
}
|
|
||||||
|
|
||||||
is ConeFlexibleType -> {
|
|
||||||
with(declarationSiteSession.typeContext) {
|
|
||||||
// Need to reproduce type approximation done for flexible types in TypeTranslator.
|
|
||||||
// For now, we replicate the current behaviour of Fir2IrTypeConverter and just take the upper bound
|
|
||||||
val upper = type.upperBound
|
|
||||||
if (upper is ConeClassLikeType) {
|
|
||||||
val lower = type.lowerBound as? ConeClassLikeType ?: error("Expecting class-like type, got ${type.lowerBound}")
|
|
||||||
val intermediate = if (lower.lookupTag == upper.lookupTag) {
|
|
||||||
lower.replaceArguments(upper.getArguments())
|
|
||||||
} else lower
|
|
||||||
val mixed = if (upper.isNullable) intermediate.makeNullable() else intermediate.makeDefinitelyNotNullOrNotNull()
|
|
||||||
mangleType(tBuilder, mixed as ConeKotlinType, declarationSiteSession)
|
|
||||||
} else mangleType(tBuilder, upper, declarationSiteSession)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is ConeDefinitelyNotNullType -> {
|
|
||||||
// E.g. not-null type parameter in Java
|
|
||||||
mangleType(tBuilder, type.original, declarationSiteSession)
|
|
||||||
}
|
|
||||||
|
|
||||||
is ConeCapturedType -> {
|
|
||||||
mangleType(tBuilder, type.lowerType ?: type.constructor.supertypes!!.first(), declarationSiteSession)
|
|
||||||
}
|
|
||||||
|
|
||||||
is ConeIntersectionType -> {
|
|
||||||
// TODO: add intersectionTypeApproximation
|
|
||||||
mangleType(tBuilder, type.intersectedTypes.first(), declarationSiteSession)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> error("Unexpected type $type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class Visitor : FirVisitorVoid() {
|
|
||||||
|
|
||||||
override fun visitElement(element: FirElement) = error("unexpected element ${element.render()}")
|
|
||||||
|
|
||||||
override fun visitRegularClass(regularClass: FirRegularClass) {
|
|
||||||
isRealExpect = isRealExpect or regularClass.isExpect
|
|
||||||
typeParameterContainers.add(regularClass)
|
|
||||||
regularClass.mangleSimpleDeclaration(regularClass.name.asString())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject) {
|
|
||||||
anonymousObject.mangleSimpleDeclaration("<anonymous>")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitVariable(variable: FirVariable) {
|
|
||||||
isRealExpect = isRealExpect or variable.isExpect
|
|
||||||
typeParameterContainers.add(variable)
|
|
||||||
variable.visitParent()
|
|
||||||
|
|
||||||
val isStaticProperty = variable.isStatic
|
|
||||||
if (isStaticProperty) {
|
|
||||||
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
|
|
||||||
}
|
|
||||||
|
|
||||||
variable.receiverParameter?.typeRef?.let {
|
|
||||||
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
|
|
||||||
mangleType(builder, it.coneType, variable.moduleData.session)
|
|
||||||
}
|
|
||||||
|
|
||||||
variable.typeParameters.withIndex().toList()
|
|
||||||
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
|
|
||||||
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, variable.moduleData.session)
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(variable.name.asString())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitProperty(property: FirProperty) {
|
|
||||||
visitVariable(property)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitField(field: FirField) {
|
override fun visitField(field: FirField) {
|
||||||
if (field is FirJavaField) {
|
if (field is FirJavaField) {
|
||||||
field.mangleSimpleDeclaration(field.name.asString())
|
field.mangleSimpleDeclaration(field.name.asString())
|
||||||
@@ -286,30 +86,5 @@ class FirJvmMangleComputer(
|
|||||||
visitVariable(field)
|
visitVariable(field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitEnumEntry(enumEntry: FirEnumEntry) {
|
|
||||||
enumEntry.mangleSimpleDeclaration(enumEntry.name.asString())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitTypeAlias(typeAlias: FirTypeAlias) =
|
|
||||||
typeAlias.mangleSimpleDeclaration(typeAlias.name.asString())
|
|
||||||
|
|
||||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
|
|
||||||
isRealExpect = isRealExpect || simpleFunction.isExpect
|
|
||||||
val isStatic = simpleFunction.isStatic
|
|
||||||
simpleFunction.mangleFunction(false, isStatic, simpleFunction)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitConstructor(constructor: FirConstructor) =
|
|
||||||
constructor.mangleFunction(isCtor = true, isStatic = false, constructor)
|
|
||||||
|
|
||||||
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
|
|
||||||
if (propertyAccessor is FirSyntheticPropertyAccessor) {
|
|
||||||
// No need to distinguish between the accessor and its delegate.
|
|
||||||
visitSimpleFunction(propertyAccessor.delegate)
|
|
||||||
} else {
|
|
||||||
propertyAccessor.mangleFunction(isCtor = false, propertyAccessor.isStatic, propertyAccessor.propertySymbol.fir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.AbstractKotlinMangler
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.signaturer.FirMangler
|
||||||
|
|
||||||
|
abstract class FirBasedKotlinMangler : AbstractKotlinMangler<FirDeclaration>(), FirMangler {
|
||||||
|
override fun FirDeclaration.mangleString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.FULL, compatibleMode).computeMangle(this)
|
||||||
|
|
||||||
|
override fun FirDeclaration.signatureString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.SIGNATURE, compatibleMode).computeMangle(this)
|
||||||
|
|
||||||
|
override fun FirDeclaration.fqnString(compatibleMode: Boolean): String = getMangleComputer(MangleMode.FQNAME, compatibleMode).computeMangle(this)
|
||||||
|
|
||||||
|
override fun FirDeclaration.isExported(compatibleMode: Boolean): Boolean = true
|
||||||
|
|
||||||
|
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<FirDeclaration> {
|
||||||
|
return object : KotlinExportChecker<FirDeclaration> {
|
||||||
|
override fun check(declaration: FirDeclaration, type: SpecialDeclarationType): Boolean = true
|
||||||
|
|
||||||
|
override fun FirDeclaration.isPlatformSpecificExported(): Boolean = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.ir.isAnonymous
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.publishedApiAnnotation
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.firClassLike
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.getContainingDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
|
abstract class FirExportCheckerVisitor : FirVisitor<Boolean, SpecialDeclarationType>(), KotlinExportChecker<FirDeclaration> {
|
||||||
|
override fun check(declaration: FirDeclaration, type: SpecialDeclarationType): Boolean =
|
||||||
|
declaration.accept(this, type)
|
||||||
|
|
||||||
|
override fun visitElement(element: FirElement, data: SpecialDeclarationType): Boolean =
|
||||||
|
TODO("Should have not been reached")
|
||||||
|
|
||||||
|
private fun <D> D.globalMemberIsExported(): Boolean where D : FirMemberDeclaration {
|
||||||
|
val visibility = visibility
|
||||||
|
if (visibility.isPublicAPI || visibility === Visibilities.Internal) return true
|
||||||
|
if (visibility === Visibilities.Local) return false
|
||||||
|
return annotations.hasAnnotation(ClassId.topLevel(publishedApiAnnotation), moduleData.session) || isPlatformSpecificExported()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D> D.isExported(): Boolean where D : FirCallableDeclaration {
|
||||||
|
val classId = symbol.callableId.classId ?: return globalMemberIsExported()
|
||||||
|
return visibility !== Visibilities.Local &&
|
||||||
|
classId.toSymbol(moduleData.session)!!.fir.accept(this@FirExportCheckerVisitor, SpecialDeclarationType.REGULAR)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <D> D.isExported(): Boolean where D : FirClassLikeDeclaration {
|
||||||
|
val containingDeclaration = getContainingDeclaration(moduleData.session) ?: return globalMemberIsExported()
|
||||||
|
return visibility !== Visibilities.Local &&
|
||||||
|
containingDeclaration.accept(this@FirExportCheckerVisitor, SpecialDeclarationType.REGULAR)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: SpecialDeclarationType): Boolean =
|
||||||
|
!simpleFunction.name.isAnonymous && simpleFunction.isExported()
|
||||||
|
|
||||||
|
override fun visitRegularClass(regularClass: FirRegularClass, data: SpecialDeclarationType): Boolean {
|
||||||
|
if (data == SpecialDeclarationType.ANON_INIT) return false
|
||||||
|
if (regularClass.name.isAnonymous) return false
|
||||||
|
return regularClass.isExported()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitConstructor(constructor: FirConstructor, data: SpecialDeclarationType): Boolean {
|
||||||
|
return constructor.returnTypeRef.firClassLike(constructor.moduleData.session)!!.isExported()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitProperty(property: FirProperty, data: SpecialDeclarationType): Boolean = property.isExported()
|
||||||
|
|
||||||
|
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: SpecialDeclarationType): Boolean = false
|
||||||
|
|
||||||
|
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: SpecialDeclarationType): Boolean = false
|
||||||
|
}
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.BaseKotlinMangleComputer
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleConstant
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.collectForMangler
|
||||||
|
import org.jetbrains.kotlin.fir.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.signaturer.irName
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base mangle computer that generates a mangled name for a Kotlin declaration represented by [FirDeclaration].
|
||||||
|
*/
|
||||||
|
open class FirMangleComputer(
|
||||||
|
builder: StringBuilder,
|
||||||
|
mode: MangleMode,
|
||||||
|
) : BaseKotlinMangleComputer<
|
||||||
|
/*Declaration=*/FirDeclaration,
|
||||||
|
/*Type=*/ConeKotlinType,
|
||||||
|
/*TypeParameter=*/ConeTypeParameterLookupTag,
|
||||||
|
/*ValueParameter=*/FirValueParameter,
|
||||||
|
/*TypeParameterContainer=*/FirMemberDeclaration,
|
||||||
|
/*FunctionDeclaration=*/FirFunction,
|
||||||
|
/*Session=*/FirSession,
|
||||||
|
>(builder, mode) {
|
||||||
|
protected open val visitor = Visitor()
|
||||||
|
|
||||||
|
override fun copy(newMode: MangleMode): FirMangleComputer =
|
||||||
|
FirMangleComputer(builder, newMode)
|
||||||
|
|
||||||
|
override fun getTypeSystemContext(session: FirSession) = object : ConeInferenceContext {
|
||||||
|
override val session: FirSession
|
||||||
|
get() = session
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
override fun FirDeclaration.visitParent() {
|
||||||
|
val (parentPackageFqName, parentClassId) = when (this) {
|
||||||
|
is FirCallableDeclaration -> this.symbol.callableId.packageName.let { it to containingClassLookupTag()?.classId }
|
||||||
|
is FirClassLikeDeclaration -> this.symbol.classId.let { it.packageFqName to it.outerClassId }
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
if (parentClassId != null && !parentClassId.isLocal) {
|
||||||
|
val parentClassLike = this.moduleData.session.symbolProvider.getClassLikeSymbolByClassId(parentClassId)?.fir
|
||||||
|
?: error("Attempt to find parent ($parentClassId) for probably-local declaration!")
|
||||||
|
if (parentClassLike is FirRegularClass || parentClassLike is FirTypeAlias) {
|
||||||
|
parentClassLike.visit()
|
||||||
|
} else {
|
||||||
|
error("Strange class-like declaration: ${parentClassLike.render()}")
|
||||||
|
}
|
||||||
|
} else if (parentClassId == null && !parentPackageFqName.isRoot) {
|
||||||
|
builder.appendName(parentPackageFqName.asString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun FirDeclaration.visit() {
|
||||||
|
accept(visitor, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirFunction.mangleFunction(isCtor: Boolean, isStatic: Boolean, container: FirDeclaration) {
|
||||||
|
|
||||||
|
isRealExpect = isRealExpect || (this as? FirMemberDeclaration)?.isExpect == true
|
||||||
|
|
||||||
|
if (container is FirMemberDeclaration) {
|
||||||
|
typeParameterContainers.add(container)
|
||||||
|
}
|
||||||
|
visitParent()
|
||||||
|
|
||||||
|
builder.appendName(MangleConstant.FUNCTION_NAME_PREFIX)
|
||||||
|
|
||||||
|
platformSpecificFunctionName()?.let {
|
||||||
|
builder.append(it)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val name = this.irName
|
||||||
|
builder.append(name.asString())
|
||||||
|
|
||||||
|
platformSpecificSuffix()?.let {
|
||||||
|
builder.append(MangleConstant.PLATFORM_FUNCTION_MARKER)
|
||||||
|
builder.append(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
mangleSignature(isCtor, isStatic, container)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirFunction.mangleSignature(isCtor: Boolean, isStatic: Boolean, container: FirDeclaration) {
|
||||||
|
if (!mode.signature) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStatic) {
|
||||||
|
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
|
||||||
|
}
|
||||||
|
|
||||||
|
contextReceivers.forEach {
|
||||||
|
builder.appendSignature(MangleConstant.CONTEXT_RECEIVER_PREFIX)
|
||||||
|
mangleType(builder, it.typeRef.coneType, moduleData.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
val receiverType = receiverParameter?.typeRef ?: (this as? FirPropertyAccessor)?.propertySymbol?.fir?.receiverParameter?.typeRef
|
||||||
|
receiverType?.let {
|
||||||
|
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
|
||||||
|
mangleType(builder, it.coneType, moduleData.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
valueParameters.collectForMangler(builder, MangleConstant.VALUE_PARAMETERS) {
|
||||||
|
appendSignature(specialValueParamPrefix(it))
|
||||||
|
mangleValueParameter(this, it, moduleData.session)
|
||||||
|
}
|
||||||
|
(container as? FirTypeParametersOwner)?.typeParameters?.withIndex()?.toList().orEmpty()
|
||||||
|
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
|
||||||
|
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, moduleData.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCtor && !returnTypeRef.isUnit && addReturnType()) {
|
||||||
|
mangleType(builder, returnTypeRef.coneType, moduleData.session)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
override fun getEffectiveParent(typeParameter: ConeTypeParameterLookupTag): FirMemberDeclaration = typeParameter.symbol.fir.run {
|
||||||
|
this.containingDeclarationSymbol.fir as FirMemberDeclaration
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderDeclaration(declaration: FirDeclaration) = declaration.render()
|
||||||
|
|
||||||
|
override fun getTypeParameterName(typeParameter: ConeTypeParameterLookupTag) = typeParameter.name.asString()
|
||||||
|
|
||||||
|
override fun isVararg(valueParameter: FirValueParameter) = valueParameter.isVararg
|
||||||
|
|
||||||
|
override fun getValueParameterType(valueParameter: FirValueParameter) = valueParameter.returnTypeRef.coneType
|
||||||
|
|
||||||
|
override fun getIndexOfTypeParameter(typeParameter: ConeTypeParameterLookupTag, container: FirMemberDeclaration) =
|
||||||
|
container.typeParameters.indexOf(typeParameter.symbol.fir)
|
||||||
|
|
||||||
|
override fun mangleType(tBuilder: StringBuilder, type: ConeKotlinType, declarationSiteSession: FirSession) {
|
||||||
|
when (type) {
|
||||||
|
is ConeLookupTagBasedType -> {
|
||||||
|
when (val symbol = type.lookupTag.toSymbol(declarationSiteSession)) {
|
||||||
|
is FirTypeAliasSymbol -> {
|
||||||
|
mangleType(tBuilder, type.fullyExpandedType(declarationSiteSession), declarationSiteSession)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
is FirClassSymbol -> with(copy(MangleMode.FQNAME)) { symbol.fir.visit() }
|
||||||
|
is FirTypeParameterSymbol -> tBuilder.mangleTypeParameterReference(symbol.toLookupTag())
|
||||||
|
// This is performed for a case with invisible class-like symbol in fake override
|
||||||
|
null -> (type.lookupTag as? ConeClassLikeLookupTag)?.let {
|
||||||
|
tBuilder.append(it.classId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mangleTypeArguments(tBuilder, type, declarationSiteSession)
|
||||||
|
|
||||||
|
if (type.isMarkedNullable) {
|
||||||
|
tBuilder.appendSignature(MangleConstant.Q_MARK)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.hasEnhancedNullability) {
|
||||||
|
tBuilder.appendSignature(MangleConstant.ENHANCED_NULLABILITY_MARK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is ConeRawType -> {
|
||||||
|
mangleType(tBuilder, type.lowerBound, declarationSiteSession)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ConeFlexibleType -> {
|
||||||
|
with(declarationSiteSession.typeContext) {
|
||||||
|
// Need to reproduce type approximation done for flexible types in TypeTranslator.
|
||||||
|
// For now, we replicate the current behaviour of Fir2IrTypeConverter and just take the upper bound
|
||||||
|
val upper = type.upperBound
|
||||||
|
if (upper is ConeClassLikeType) {
|
||||||
|
val lower = type.lowerBound as? ConeClassLikeType ?: error("Expecting class-like type, got ${type.lowerBound}")
|
||||||
|
val intermediate = if (lower.lookupTag == upper.lookupTag) {
|
||||||
|
lower.replaceArguments(upper.getArguments())
|
||||||
|
} else lower
|
||||||
|
val mixed = if (upper.isNullable) intermediate.makeNullable() else intermediate.makeDefinitelyNotNullOrNotNull()
|
||||||
|
mangleType(tBuilder, mixed as ConeKotlinType, declarationSiteSession)
|
||||||
|
} else mangleType(tBuilder, upper, declarationSiteSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is ConeDefinitelyNotNullType -> {
|
||||||
|
// E.g. not-null type parameter in Java
|
||||||
|
mangleType(tBuilder, type.original, declarationSiteSession)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ConeCapturedType -> {
|
||||||
|
mangleType(tBuilder, type.lowerType ?: type.constructor.supertypes!!.first(), declarationSiteSession)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ConeIntersectionType -> {
|
||||||
|
// TODO: add intersectionTypeApproximation
|
||||||
|
mangleType(tBuilder, type.intersectedTypes.first(), declarationSiteSession)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> error("Unexpected type $type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open inner class Visitor : FirVisitorVoid() {
|
||||||
|
|
||||||
|
override fun visitElement(element: FirElement) = error("unexpected element ${element.render()}")
|
||||||
|
|
||||||
|
override fun visitRegularClass(regularClass: FirRegularClass) {
|
||||||
|
isRealExpect = isRealExpect or regularClass.isExpect
|
||||||
|
typeParameterContainers.add(regularClass)
|
||||||
|
regularClass.mangleSimpleDeclaration(regularClass.name.asString())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject) {
|
||||||
|
anonymousObject.mangleSimpleDeclaration("<anonymous>")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVariable(variable: FirVariable) {
|
||||||
|
isRealExpect = isRealExpect or variable.isExpect
|
||||||
|
typeParameterContainers.add(variable)
|
||||||
|
variable.visitParent()
|
||||||
|
|
||||||
|
val isStaticProperty = variable.isStatic
|
||||||
|
if (isStaticProperty) {
|
||||||
|
builder.appendSignature(MangleConstant.STATIC_MEMBER_MARK)
|
||||||
|
}
|
||||||
|
|
||||||
|
variable.receiverParameter?.typeRef?.let {
|
||||||
|
builder.appendSignature(MangleConstant.EXTENSION_RECEIVER_PREFIX)
|
||||||
|
mangleType(builder, it.coneType, variable.moduleData.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
variable.typeParameters.withIndex().toList()
|
||||||
|
.collectForMangler(builder, MangleConstant.TYPE_PARAMETERS) { (index, typeParameter) ->
|
||||||
|
mangleTypeParameter(this, typeParameter.symbol.toLookupTag(), index, variable.moduleData.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(variable.name.asString())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitProperty(property: FirProperty) {
|
||||||
|
visitVariable(property)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitField(field: FirField) {
|
||||||
|
visitVariable(field)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnumEntry(enumEntry: FirEnumEntry) {
|
||||||
|
enumEntry.mangleSimpleDeclaration(enumEntry.name.asString())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeAlias(typeAlias: FirTypeAlias) =
|
||||||
|
typeAlias.mangleSimpleDeclaration(typeAlias.name.asString())
|
||||||
|
|
||||||
|
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
|
||||||
|
isRealExpect = isRealExpect || simpleFunction.isExpect
|
||||||
|
val isStatic = simpleFunction.isStatic
|
||||||
|
simpleFunction.mangleFunction(false, isStatic, simpleFunction)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitConstructor(constructor: FirConstructor) =
|
||||||
|
constructor.mangleFunction(isCtor = true, isStatic = false, constructor)
|
||||||
|
|
||||||
|
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
|
||||||
|
if (propertyAccessor is FirSyntheticPropertyAccessor) {
|
||||||
|
// No need to distinguish between the accessor and its delegate.
|
||||||
|
visitSimpleFunction(propertyAccessor.delegate)
|
||||||
|
} else {
|
||||||
|
propertyAccessor.mangleFunction(isCtor = false, propertyAccessor.isStatic, propertyAccessor.propertySymbol.fir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-2
@@ -221,8 +221,6 @@ internal class AdapterGenerator(
|
|||||||
isExpect = false,
|
isExpect = false,
|
||||||
isFakeOverride = false
|
isFakeOverride = false
|
||||||
).also { irAdapterFunction ->
|
).also { irAdapterFunction ->
|
||||||
irAdapterFunction.metadata = FirMetadataSource.Function(firAdaptee)
|
|
||||||
|
|
||||||
symbolTable.enterScope(irAdapterFunction)
|
symbolTable.enterScope(irAdapterFunction)
|
||||||
irAdapterFunction.dispatchReceiverParameter = null
|
irAdapterFunction.dispatchReceiverParameter = null
|
||||||
val boundReceiver = boundDispatchReceiver ?: boundExtensionReceiver
|
val boundReceiver = boundDispatchReceiver ?: boundExtensionReceiver
|
||||||
|
|||||||
@@ -5,10 +5,40 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.signaturer
|
package org.jetbrains.kotlin.fir.signaturer
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.AbstractKotlinMangler
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinMangleComputer
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
|
||||||
|
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrMetadataSourceOwner
|
||||||
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
import org.jetbrains.kotlin.ir.util.KotlinMangler
|
||||||
|
|
||||||
interface FirMangler : KotlinMangler<FirDeclaration> {
|
interface FirMangler : KotlinMangler<FirDeclaration> {
|
||||||
override val manglerName: String
|
override val manglerName: String
|
||||||
get() = "Fir"
|
get() = "Fir"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Ir2FirManglerAdapter(private val delegate: FirMangler) : AbstractKotlinMangler<IrDeclaration>(),
|
||||||
|
KotlinMangler.IrMangler {
|
||||||
|
override val manglerName: String
|
||||||
|
get() = delegate.manglerName
|
||||||
|
|
||||||
|
private fun IrDeclaration.fir(): FirDeclaration = ((this as IrMetadataSourceOwner).metadata as FirMetadataSource).fir!!
|
||||||
|
|
||||||
|
override fun IrDeclaration.isExported(compatibleMode: Boolean): Boolean = delegate.run { fir().isExported(compatibleMode) }
|
||||||
|
|
||||||
|
override fun IrDeclaration.mangleString(compatibleMode: Boolean): String = delegate.run { fir().mangleString(compatibleMode) }
|
||||||
|
|
||||||
|
override fun IrDeclaration.signatureString(compatibleMode: Boolean): String = delegate.run { fir().signatureString(compatibleMode) }
|
||||||
|
|
||||||
|
override fun IrDeclaration.fqnString(compatibleMode: Boolean): String = delegate.run { fir().fqnString(compatibleMode) }
|
||||||
|
|
||||||
|
override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): KotlinMangleComputer<IrDeclaration> =
|
||||||
|
error("Should not have been reached")
|
||||||
|
|
||||||
|
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<IrDeclaration> {
|
||||||
|
error("Should not be called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+1
-2
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.fir.FirSession
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* That class is expected to work just the same as FirStandardOverrideChecker for regular members,
|
* That class is expected to work just the same as FirStandardOverrideChecker for regular members,
|
||||||
@@ -20,7 +19,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
|||||||
* while in Java class they would be treated equally.
|
* while in Java class they would be treated equally.
|
||||||
*/
|
*/
|
||||||
class FirIntersectionScopeOverrideChecker(session: FirSession) : FirOverrideChecker {
|
class FirIntersectionScopeOverrideChecker(session: FirSession) : FirOverrideChecker {
|
||||||
private val standardOverrideChecker = FirStandardOverrideChecker(session)
|
private val standardOverrideChecker = session.firOverrideChecker
|
||||||
private val platformSpecificOverridabilityRules = session.platformSpecificOverridabilityRules
|
private val platformSpecificOverridabilityRules = session.platformSpecificOverridabilityRules
|
||||||
|
|
||||||
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean {
|
||||||
|
|||||||
@@ -5,12 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.scopes
|
package org.jetbrains.kotlin.fir.scopes
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
|
||||||
interface FirOverrideChecker {
|
interface FirOverrideChecker : FirSessionComponent {
|
||||||
fun isOverriddenFunction(
|
fun isOverriddenFunction(
|
||||||
overrideCandidate: FirSimpleFunction,
|
overrideCandidate: FirSimpleFunction,
|
||||||
baseDeclaration: FirSimpleFunction
|
baseDeclaration: FirSimpleFunction
|
||||||
@@ -26,3 +28,5 @@ fun FirOverrideChecker.isOverriddenFunction(
|
|||||||
overrideCandidate: FirNamedFunctionSymbol,
|
overrideCandidate: FirNamedFunctionSymbol,
|
||||||
baseDeclaration: FirNamedFunctionSymbol
|
baseDeclaration: FirNamedFunctionSymbol
|
||||||
): Boolean = isOverriddenFunction(overrideCandidate.fir, baseDeclaration.fir)
|
): Boolean = isOverriddenFunction(overrideCandidate.fir, baseDeclaration.fir)
|
||||||
|
|
||||||
|
val FirSession.firOverrideChecker: FirOverrideChecker by FirSession.sessionComponentAccessor()
|
||||||
|
|||||||
+2
-1
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
|||||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
|
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.firOverrideChecker
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ class FirClassUseSiteMemberScope(
|
|||||||
) : AbstractFirUseSiteMemberScope(
|
) : AbstractFirUseSiteMemberScope(
|
||||||
klass.classId,
|
klass.classId,
|
||||||
session,
|
session,
|
||||||
FirStandardOverrideChecker(session),
|
session.firOverrideChecker,
|
||||||
superTypeScopes,
|
superTypeScopes,
|
||||||
klass.defaultType(),
|
klass.defaultType(),
|
||||||
declaredMemberScope
|
declaredMemberScope
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ class FirDelegatedMemberScope(
|
|||||||
private val delegateFields: List<FirField>,
|
private val delegateFields: List<FirField>,
|
||||||
) : FirContainingNamesAwareScope() {
|
) : FirContainingNamesAwareScope() {
|
||||||
private val dispatchReceiverType = containingClass.defaultType()
|
private val dispatchReceiverType = containingClass.defaultType()
|
||||||
private val overrideChecker = FirStandardOverrideChecker(session)
|
private val overrideChecker = session.firOverrideChecker
|
||||||
|
|
||||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||||
declaredMemberScope.processFunctionsByName(name, processor)
|
declaredMemberScope.processFunctionsByName(name, processor)
|
||||||
|
|||||||
+11
-3
@@ -15,7 +15,15 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
|
||||||
class ManglerChecker(vararg _manglers: KotlinMangler<IrDeclaration>) : IrElementVisitorVoid {
|
class ManglerChecker(
|
||||||
|
vararg _manglers: KotlinMangler<IrDeclaration>,
|
||||||
|
private val needsChecking: (IrDeclarationBase) -> Boolean = hasDescriptor
|
||||||
|
) : IrElementVisitorVoid {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val hasDescriptor: (IrDeclarationBase) -> Boolean = { it.symbol.hasDescriptor }
|
||||||
|
val hasMetadata: (IrDeclarationBase) -> Boolean = { (it as? IrMetadataSourceOwner)?.metadata != null }
|
||||||
|
}
|
||||||
|
|
||||||
private val manglers = _manglers.toList()
|
private val manglers = _manglers.toList()
|
||||||
|
|
||||||
@@ -29,7 +37,7 @@ class ManglerChecker(vararg _manglers: KotlinMangler<IrDeclaration>) : IrElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDeclaration(declaration: IrDeclarationBase, data: Nothing?): Boolean {
|
override fun visitDeclaration(declaration: IrDeclarationBase, data: Nothing?): Boolean {
|
||||||
if (!declaration.symbol.hasDescriptor) return true
|
if (!needsChecking(declaration)) return true
|
||||||
|
|
||||||
if (declaration.parent is IrPackageFragment) {
|
if (declaration.parent is IrPackageFragment) {
|
||||||
val vis = declaration as IrDeclarationWithVisibility
|
val vis = declaration as IrDeclarationWithVisibility
|
||||||
@@ -87,7 +95,7 @@ class ManglerChecker(vararg _manglers: KotlinMangler<IrDeclaration>) : IrElement
|
|||||||
if (declaration is IrErrorDeclaration) return
|
if (declaration is IrErrorDeclaration) return
|
||||||
|
|
||||||
val exported = manglers.checkAllEqual(false, { isExportCheck(declaration) }) { m1, r1, m2, r2 ->
|
val exported = manglers.checkAllEqual(false, { isExportCheck(declaration) }) { m1, r1, m2, r2 ->
|
||||||
error("${declaration.render()}\n ${m1.manglerName}: $r1\n ${m2.manglerName}: $r2\n")
|
error("isExportCheck: ${declaration.render()}\n ${m1.manglerName}: $r1\n ${m2.manglerName}: $r2\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!exported) return
|
if (!exported) return
|
||||||
|
|||||||
+1
-1
@@ -36,4 +36,4 @@ fun <T> Iterable<T>.collectForMangler(builder: StringBuilder, params: MangleCons
|
|||||||
builder.append(params.suffix)
|
builder.append(params.suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val publishedApiAnnotation = FqName("kotlin.PublishedApi")
|
val publishedApiAnnotation = FqName("kotlin.PublishedApi")
|
||||||
|
|||||||
+11
-5
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan
|
package org.jetbrains.kotlin.backend.konan
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer
|
import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer
|
||||||
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
import org.jetbrains.kotlin.backend.konan.driver.PhaseContext
|
||||||
import org.jetbrains.kotlin.backend.konan.driver.phases.Fir2IrOutput
|
import org.jetbrains.kotlin.backend.konan.driver.phases.Fir2IrOutput
|
||||||
@@ -18,16 +19,15 @@ import org.jetbrains.kotlin.config.languageVersionSettings
|
|||||||
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentTypeTransformer
|
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentTypeTransformer
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
|
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
|
||||||
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
|
||||||
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
|
import org.jetbrains.kotlin.fir.backend.*
|
||||||
import org.jetbrains.kotlin.fir.backend.Fir2IrPluginContext
|
|
||||||
import org.jetbrains.kotlin.fir.backend.Fir2IrVisibilityConverter
|
|
||||||
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
||||||
import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
|
import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
|
||||||
|
import org.jetbrains.kotlin.fir.signaturer.Ir2FirManglerAdapter
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
|
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
|
||||||
@@ -74,10 +74,17 @@ internal fun PhaseContext.fir2Ir(
|
|||||||
linkViaSignatures = false,
|
linkViaSignatures = false,
|
||||||
signatureComposerCreator = null,
|
signatureComposerCreator = null,
|
||||||
irMangler = KonanManglerIr,
|
irMangler = KonanManglerIr,
|
||||||
|
firManglerCreator = { FirNativeKotlinMangler() },
|
||||||
visibilityConverter = Fir2IrVisibilityConverter.Default,
|
visibilityConverter = Fir2IrVisibilityConverter.Default,
|
||||||
diagnosticReporter = diagnosticsReporter,
|
diagnosticReporter = diagnosticsReporter,
|
||||||
languageVersionSettings = configuration.languageVersionSettings,
|
languageVersionSettings = configuration.languageVersionSettings,
|
||||||
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
|
kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance,
|
||||||
|
fir2IrResultPostCompute = {
|
||||||
|
// it's important to compare manglers before actualization, since IR will be actualized, while FIR won't
|
||||||
|
irModuleFragment.acceptVoid(
|
||||||
|
ManglerChecker(KonanManglerIr, Ir2FirManglerAdapter(FirNativeKotlinMangler()), needsChecking = ManglerChecker.hasMetadata)
|
||||||
|
)
|
||||||
|
}
|
||||||
).also {
|
).also {
|
||||||
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors }
|
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors }
|
||||||
}
|
}
|
||||||
@@ -86,7 +93,6 @@ internal fun PhaseContext.fir2Ir(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val symbols = createKonanSymbols(irModuleFragment, components, pluginContext)
|
val symbols = createKonanSymbols(irModuleFragment, components, pluginContext)
|
||||||
// TODO KT-55580 Invoke CopyDefaultValuesToActualPhase, same as PsiToir phase does.
|
|
||||||
|
|
||||||
val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
|
val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
|
||||||
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
|
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
|
||||||
|
|||||||
+7
-5
@@ -10,20 +10,19 @@ import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
|||||||
import org.jetbrains.kotlin.cli.common.prepareNativeSessions
|
import org.jetbrains.kotlin.cli.common.prepareNativeSessions
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
|
||||||
import org.jetbrains.kotlin.fir.BinaryModuleData
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.DependencyListForCliModule
|
|
||||||
import org.jetbrains.kotlin.fir.FirModuleCapabilities
|
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||||
import org.jetbrains.kotlin.fir.pipeline.FirResult
|
import org.jetbrains.kotlin.fir.pipeline.FirResult
|
||||||
import org.jetbrains.kotlin.fir.pipeline.buildResolveAndCheckFir
|
import org.jetbrains.kotlin.fir.pipeline.buildResolveAndCheckFir
|
||||||
import org.jetbrains.kotlin.fir.render
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.ImplicitIntegerCoercionModuleCapability
|
import org.jetbrains.kotlin.fir.resolve.ImplicitIntegerCoercionModuleCapability
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||||
import org.jetbrains.kotlin.library.isInterop
|
import org.jetbrains.kotlin.library.isInterop
|
||||||
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
|
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.platform.CommonPlatforms
|
import org.jetbrains.kotlin.platform.CommonPlatforms
|
||||||
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
|
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
|
||||||
|
|
||||||
|
@OptIn(SessionConfiguration::class)
|
||||||
internal fun PhaseContext.firFrontend(input: KotlinCoreEnvironment): FirOutput {
|
internal fun PhaseContext.firFrontend(input: KotlinCoreEnvironment): FirOutput {
|
||||||
val configuration = input.configuration
|
val configuration = input.configuration
|
||||||
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||||
@@ -56,7 +55,10 @@ internal fun PhaseContext.firFrontend(input: KotlinCoreEnvironment): FirOutput {
|
|||||||
|
|
||||||
val sessionsWithSources = prepareNativeSessions(
|
val sessionsWithSources = prepareNativeSessions(
|
||||||
ktFiles, configuration, mainModuleName, resolvedLibraries, dependencyList,
|
ktFiles, configuration, mainModuleName, resolvedLibraries, dependencyList,
|
||||||
extensionRegistrars, isCommonSourceForPsi, fileBelongsToModuleForPsi
|
extensionRegistrars, isCommonSourceForPsi, fileBelongsToModuleForPsi,
|
||||||
|
registerExtraComponents = {
|
||||||
|
it.register(FirOverrideChecker::class, FirNativeOverrideChecker(it))
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
val outputs = sessionsWithSources.map { (session, sources) ->
|
val outputs = sessionsWithSources.map { (session, sources) ->
|
||||||
|
|||||||
+121
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend.konan
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinExportChecker
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.KotlinMangleComputer
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.MangleMode
|
||||||
|
import org.jetbrains.kotlin.backend.common.serialization.mangle.SpecialDeclarationType
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.backend.FirBasedKotlinMangler
|
||||||
|
import org.jetbrains.kotlin.fir.backend.FirExportCheckerVisitor
|
||||||
|
import org.jetbrains.kotlin.fir.backend.FirMangleComputer
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
|
class FirNativeKotlinMangler : FirBasedKotlinMangler() {
|
||||||
|
override fun getMangleComputer(mode: MangleMode, compatibleMode: Boolean): KotlinMangleComputer<FirDeclaration> {
|
||||||
|
return FirNativeKotlinMangleComputer(StringBuilder(256), mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getExportChecker(compatibleMode: Boolean): KotlinExportChecker<FirDeclaration> = FirNativeExportCheckerVisitor()
|
||||||
|
|
||||||
|
override fun FirDeclaration.isExported(compatibleMode: Boolean): Boolean =
|
||||||
|
getExportChecker(compatibleMode).check(this, SpecialDeclarationType.REGULAR)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FirNativeExportCheckerVisitor : FirExportCheckerVisitor() {
|
||||||
|
/**
|
||||||
|
* mimics AbstractKonanDescriptorMangler::DeclarationDescriptor.isPlatformSpecificExport()
|
||||||
|
*/
|
||||||
|
override fun FirDeclaration.isPlatformSpecificExported(): Boolean {
|
||||||
|
fun List<FirAnnotation>.hasAnnotation(fqName: FqName) = hasAnnotation(ClassId.topLevel(fqName), moduleData.session)
|
||||||
|
|
||||||
|
if (this is FirCallableDeclaration && isSubstitutionOrIntersectionOverride)
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (annotations.hasAnnotation(RuntimeNames.symbolNameAnnotation)) {
|
||||||
|
// Treat any `@SymbolName` declaration as exported.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (annotations.hasAnnotation(KonanFqNames.gcUnsafeCall)) {
|
||||||
|
// Treat any `@GCUnsafeCall` declaration as exported.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)) {
|
||||||
|
// Treat any `@ExportForCppRuntime` declaration as exported.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (annotations.hasAnnotation(RuntimeNames.cnameAnnotation)) {
|
||||||
|
// Treat `@CName` declaration as exported.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FirNativeKotlinMangleComputer(
|
||||||
|
builder: StringBuilder,
|
||||||
|
mode: MangleMode,
|
||||||
|
) : FirMangleComputer(builder, mode) {
|
||||||
|
override fun copy(newMode: MangleMode): FirNativeKotlinMangleComputer =
|
||||||
|
FirNativeKotlinMangleComputer(builder, newMode)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mimics FunctionDescriptor.platformSpecificFunctionName()
|
||||||
|
*/
|
||||||
|
override fun FirFunction.platformSpecificFunctionName(): String? {
|
||||||
|
val session = moduleData.session
|
||||||
|
val scopeSession = ScopeSession()
|
||||||
|
getInitMethodIfObjCConstructor(session, scopeSession)
|
||||||
|
?.getObjCMethodInfoFromOverriddenFunctions(session, scopeSession)
|
||||||
|
?.let {
|
||||||
|
return buildString {
|
||||||
|
receiverParameter?.let {
|
||||||
|
append(it.getTypeName(session))
|
||||||
|
append(".")
|
||||||
|
}
|
||||||
|
|
||||||
|
append("objc:")
|
||||||
|
append(it.selector)
|
||||||
|
if ((this@platformSpecificFunctionName is FirConstructor) && isObjCConstructor(session)) append("#Constructor")
|
||||||
|
|
||||||
|
if (this@platformSpecificFunctionName is FirPropertyAccessor) {
|
||||||
|
append("#Accessor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun FirFunction.specialValueParamPrefix(param: FirValueParameter): String {
|
||||||
|
val session = moduleData.session
|
||||||
|
return if (this.hasObjCMethodAnnotation(session) || this.hasObjCFactoryAnnotation(session) || this.isObjCClassMethod(session))
|
||||||
|
"${param.name}:"
|
||||||
|
else
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirReceiverParameter.getTypeName(session: FirSession): String {
|
||||||
|
return when (val symbol = typeRef.coneType.toSymbol(session)) {
|
||||||
|
is FirClassLikeSymbol -> symbol.classId.shortClassName.asString()
|
||||||
|
is FirTypeParameterSymbol -> symbol.name.asString()
|
||||||
|
else -> error("Unexpected symbol class: ${symbol?.javaClass?.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend.konan
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
||||||
|
|
||||||
|
class FirNativeOverrideChecker(private val session: FirSession) : FirOverrideChecker {
|
||||||
|
private val standardOverrideChecker = FirStandardOverrideChecker(session)
|
||||||
|
|
||||||
|
override fun isOverriddenFunction(overrideCandidate: FirSimpleFunction, baseDeclaration: FirSimpleFunction): Boolean =
|
||||||
|
overrideCandidate.isPlatformOverriddenFunction(session, baseDeclaration)
|
||||||
|
?: standardOverrideChecker.isOverriddenFunction(overrideCandidate, baseDeclaration)
|
||||||
|
|
||||||
|
override fun isOverriddenProperty(overrideCandidate: FirCallableDeclaration, baseDeclaration: FirProperty): Boolean =
|
||||||
|
overrideCandidate.isPlatformOverriddenProperty(baseDeclaration)
|
||||||
|
?: standardOverrideChecker.isOverriddenProperty(overrideCandidate, baseDeclaration)
|
||||||
|
|
||||||
|
// FIXME KT-57640: Revise the necessity of platform-specific property overridability handling
|
||||||
|
private fun FirCallableDeclaration.isPlatformOverriddenProperty(baseDeclaration: FirProperty): Boolean? {
|
||||||
|
if (this !is FirProperty || name != baseDeclaration.name) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (this.isExternalObjCClassProperty(session) && baseDeclaration.isExternalObjCClassProperty(session))
|
||||||
|
return true
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mimics ObjCOverridabilityCondition.isOverridable
|
||||||
|
*/
|
||||||
|
private fun FirSimpleFunction.isPlatformOverriddenFunction(session: FirSession, baseDeclaration: FirSimpleFunction): Boolean? {
|
||||||
|
if (this.name != baseDeclaration.name) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val superInfo = baseDeclaration.decodeObjCMethodAnnotation(session) ?: return null
|
||||||
|
val subInfo = decodeObjCMethodAnnotation(session)
|
||||||
|
return if (subInfo != null) {
|
||||||
|
// Overriding Objective-C method by Objective-C method in interop stubs.
|
||||||
|
// Don't even check method signatures, so this check is weaker than the standard one
|
||||||
|
superInfo.selector == subInfo.selector
|
||||||
|
} else {
|
||||||
|
// Overriding Objective-C method by Kotlin method.
|
||||||
|
if (!parameterNamesMatch(this, baseDeclaration)) false else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mimics ObjCInteropKt.parameterNamesMatch
|
||||||
|
*/
|
||||||
|
private fun parameterNamesMatch(first: FirSimpleFunction, second: FirSimpleFunction): Boolean {
|
||||||
|
// The original Objective-C method selector is represented as
|
||||||
|
// function name and parameter names (except first).
|
||||||
|
|
||||||
|
if (first.valueParameters.size != second.valueParameters.size) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
first.valueParameters.forEachIndexed { index, parameter ->
|
||||||
|
if (index > 0 && parameter.name != second.valueParameters[index].name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
+156
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* 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.backend.konan
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.getContainingClass
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.getContainingDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.providers.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.scopeForClass
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.classId
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
|
|
||||||
|
private val objCDirectClassId = ClassId.topLevel(objCDirectFqName)
|
||||||
|
private val objCMethodClassId = ClassId.topLevel(objCMethodFqName)
|
||||||
|
private val objCObjectClassId = ClassId.topLevel(objCObjectFqName)
|
||||||
|
private val objCFactoryClassId = ClassId.topLevel(objCFactoryFqName)
|
||||||
|
private val objCConstructorClassId = ClassId.topLevel(objCConstructorFqName)
|
||||||
|
private val externalObjCClassClassId = ClassId.topLevel(externalObjCClassFqName)
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
internal fun FirFunction.getObjCMethodInfoFromOverriddenFunctions(session: FirSession, scopeSession: ScopeSession): ObjCMethodInfo? {
|
||||||
|
decodeObjCMethodAnnotation(session)?.let {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
// recursively find ObjCMethod annotation in getDirectOverriddenFunctions() (same as `overriddenDescriptors` in K1)
|
||||||
|
return when (val symbol = this.symbol) {
|
||||||
|
is FirNamedFunctionSymbol -> {
|
||||||
|
val firClassSymbol = containingClassLookupTag()?.toSymbol(session) as FirClassSymbol<*>?
|
||||||
|
firClassSymbol?.let {
|
||||||
|
val unsubstitutedScope = it.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false, memberRequiredPhase = null)
|
||||||
|
// call of `processFunctionsByName()` is needed only for necessary side-effect before `getDirectOverriddenFunctions` call
|
||||||
|
unsubstitutedScope.processFunctionsByName(symbol.name) {}
|
||||||
|
unsubstitutedScope.getDirectOverriddenFunctions(symbol).firstNotNullOfOrNull {
|
||||||
|
it.fir.getObjCMethodInfoFromOverriddenFunctions(session, scopeSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mimics ConstructorDescriptor.getObjCInitMethod()
|
||||||
|
*/
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
private fun FirConstructor.getObjCInitMethod(session: FirSession, scopeSession: ScopeSession): FirFunction? {
|
||||||
|
this.annotations.getAnnotationByClassId(objCConstructorClassId, session)?.let { annotation ->
|
||||||
|
val initSelector: String = annotation.constStringArgument("initSelector")
|
||||||
|
val classSymbol = containingClassLookupTag()?.toSymbol(session) as FirClassSymbol<*>
|
||||||
|
val initSelectors = mutableListOf<FirFunction>()
|
||||||
|
classSymbol.fir.scopeForClass(ConeSubstitutor.Empty, session, scopeSession, classSymbol.toLookupTag(), memberRequiredPhase = null)
|
||||||
|
.processAllFunctions {
|
||||||
|
if (it.fir.decodeObjCMethodAnnotation(session)?.selector == initSelector)
|
||||||
|
initSelectors.add(it.fir)
|
||||||
|
}
|
||||||
|
return initSelectors.singleOrNull()
|
||||||
|
?: error("expected one init method for $classSymbol $initSelector, got ${initSelectors.size}")
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mimics FunctionDescriptor.decodeObjCMethodAnnotation()
|
||||||
|
*/
|
||||||
|
internal fun FirFunction.decodeObjCMethodAnnotation(session: FirSession): ObjCMethodInfo? =
|
||||||
|
annotations.getAnnotationByClassId(objCMethodClassId, session)?.let {
|
||||||
|
ObjCMethodInfo(
|
||||||
|
selector = it.constStringArgument("selector"),
|
||||||
|
encoding = it.constStringArgument("encoding"),
|
||||||
|
isStret = it.constBooleanArgumentOrNull("isStret") ?: false,
|
||||||
|
directSymbol = annotations.getAnnotationByClassId(objCDirectClassId, session)?.constStringArgument("symbol"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun FirAnnotation.constStringArgument(argumentName: String): String =
|
||||||
|
constArgument(argumentName) as? String ?: error("Expected string constant value of argument '$argumentName' at annotation $this")
|
||||||
|
|
||||||
|
private fun FirAnnotation.constBooleanArgumentOrNull(argumentName: String): Boolean? =
|
||||||
|
constArgument(argumentName) as Boolean?
|
||||||
|
|
||||||
|
private fun FirAnnotation.constArgument(argumentName: String) =
|
||||||
|
(argumentMapping.mapping[Name.identifier(argumentName)] as? FirConstExpression<*>)?.value
|
||||||
|
|
||||||
|
internal fun FirFunction.hasObjCFactoryAnnotation(session: FirSession) = this.annotations.hasAnnotation(objCFactoryClassId, session)
|
||||||
|
|
||||||
|
internal fun FirFunction.hasObjCMethodAnnotation(session: FirSession) = this.annotations.hasAnnotation(objCMethodClassId, session)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* almost mimics FunctionDescriptor.isObjCClassMethod(), apart from `it.isObjCClass()` changed to `it.symbol.isObjCClass(session)` for simplicity
|
||||||
|
*/
|
||||||
|
internal fun FirFunction.isObjCClassMethod(session: FirSession) =
|
||||||
|
getContainingClass(session).let { it is FirClass && it.symbol.isObjCClass(session) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mimics ConstructorDescriptor.isObjCConstructor()
|
||||||
|
*/
|
||||||
|
internal fun FirConstructor.isObjCConstructor(session: FirSession) =
|
||||||
|
this.annotations.hasAnnotation(objCConstructorClassId, session)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mimics IrClass.isObjCClass()
|
||||||
|
*/
|
||||||
|
private fun FirClassSymbol<*>.isObjCClass(session: FirSession) = classId.packageFqName != interopPackageName &&
|
||||||
|
selfOrAnySuperClass(session) {
|
||||||
|
it.classId == objCObjectClassId
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* almost mimics `IrClass.selfOrAnySuperClass()` apart from using of classsymbol instead of class itself, to use `classId.toSymbol()`
|
||||||
|
*/
|
||||||
|
private fun FirClassSymbol<*>.selfOrAnySuperClass(session: FirSession, pred: (FirClassSymbol<*>) -> Boolean): Boolean =
|
||||||
|
DFS.ifAny(
|
||||||
|
listOf(this),
|
||||||
|
{ current -> current.resolvedSuperTypes.mapNotNull { it.classId?.toSymbol(session) as? FirClassSymbol } },
|
||||||
|
pred
|
||||||
|
)
|
||||||
|
|
||||||
|
internal fun FirFunction.getInitMethodIfObjCConstructor(session: FirSession, scopeSession: ScopeSession): FirFunction? =
|
||||||
|
if (this is FirConstructor && isObjCConstructor(session))
|
||||||
|
getObjCInitMethod(session, scopeSession)
|
||||||
|
else
|
||||||
|
this
|
||||||
|
|
||||||
|
internal fun FirProperty.isExternalObjCClassProperty(session: FirSession) =
|
||||||
|
(getContainingClassSymbol(session) as? FirClassSymbol)?.isExternalObjCClass(session) == true
|
||||||
|
|
||||||
|
internal fun FirClassSymbol<*>.isExternalObjCClass(session: FirSession): Boolean =
|
||||||
|
isObjCClass(session) &&
|
||||||
|
parentsWithSelf(session).filterIsInstance<FirClass>().any {
|
||||||
|
it.hasAnnotation(externalObjCClassClassId, session)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
fun FirClassSymbol<*>.parentsWithSelf(session: FirSession): Sequence<FirClassLikeDeclaration> {
|
||||||
|
return generateSequence<FirClassLikeDeclaration>(fir) { it.getContainingDeclaration(session) }
|
||||||
|
}
|
||||||
+8
-17
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.descriptors.IrBasedClassConstructorDescriptor
|
import org.jetbrains.kotlin.ir.descriptors.IrBasedClassConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.getPublicSignature
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -30,21 +29,15 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
|
|||||||
|
|
||||||
internal val interopPackageName = InteropFqNames.packageName
|
internal val interopPackageName = InteropFqNames.packageName
|
||||||
internal val objCObjectFqName = interopPackageName.child(Name.identifier("ObjCObject"))
|
internal val objCObjectFqName = interopPackageName.child(Name.identifier("ObjCObject"))
|
||||||
internal val objCObjectIdSignature = getTopLevelPublicSignature(objCObjectFqName)
|
|
||||||
private val objCClassFqName = interopPackageName.child(Name.identifier("ObjCClass"))
|
private val objCClassFqName = interopPackageName.child(Name.identifier("ObjCClass"))
|
||||||
private val objCClassIdSignature = getTopLevelPublicSignature(objCClassFqName)
|
|
||||||
private val objCProtocolFqName = interopPackageName.child(Name.identifier("ObjCProtocol"))
|
private val objCProtocolFqName = interopPackageName.child(Name.identifier("ObjCProtocol"))
|
||||||
private val objCProtocolIdSignature = getTopLevelPublicSignature(objCProtocolFqName)
|
|
||||||
internal val externalObjCClassFqName = interopPackageName.child(Name.identifier("ExternalObjCClass"))
|
internal val externalObjCClassFqName = interopPackageName.child(Name.identifier("ExternalObjCClass"))
|
||||||
private val objCMethodFqName = interopPackageName.child(Name.identifier("ObjCMethod"))
|
internal val objCDirectFqName = interopPackageName.child(Name.identifier("ObjCDirect"))
|
||||||
private val objCDirectFqName = interopPackageName.child(Name.identifier("ObjCDirect"))
|
internal val objCMethodFqName = interopPackageName.child(Name.identifier("ObjCMethod"))
|
||||||
private val objCConstructorFqName = FqName("kotlinx.cinterop.ObjCConstructor")
|
internal val objCConstructorFqName = FqName("kotlinx.cinterop.ObjCConstructor")
|
||||||
private val objCFactoryFqName = interopPackageName.child(Name.identifier("ObjCFactory"))
|
internal val objCFactoryFqName = interopPackageName.child(Name.identifier("ObjCFactory"))
|
||||||
private val objcnamesForwardDeclarationsPackageName = Name.identifier("objcnames")
|
private val objcnamesForwardDeclarationsPackageName = Name.identifier("objcnames")
|
||||||
|
|
||||||
private fun getTopLevelPublicSignature(fqName: FqName): IdSignature.CommonSignature =
|
|
||||||
getPublicSignature(fqName.parent(), fqName.shortName().asString())
|
|
||||||
|
|
||||||
fun ClassDescriptor.isObjCClass(): Boolean =
|
fun ClassDescriptor.isObjCClass(): Boolean =
|
||||||
this.containingDeclaration.fqNameSafe != interopPackageName &&
|
this.containingDeclaration.fqNameSafe != interopPackageName &&
|
||||||
this.getAllSuperClassifiers().any { it.fqNameSafe == objCObjectFqName } // TODO: this is not cheap. Cache me!
|
this.getAllSuperClassifiers().any { it.fqNameSafe == objCObjectFqName } // TODO: this is not cheap. Cache me!
|
||||||
@@ -59,7 +52,7 @@ private fun IrClass.selfOrAnySuperClass(pred: (IrClass) -> Boolean): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun IrClass.isObjCClass() = this.packageFqName != interopPackageName &&
|
internal fun IrClass.isObjCClass() = this.packageFqName != interopPackageName &&
|
||||||
selfOrAnySuperClass { objCObjectIdSignature == it.symbol.signature }
|
selfOrAnySuperClass { it.hasEqualFqName(objCObjectFqName) }
|
||||||
|
|
||||||
fun ClassDescriptor.isExternalObjCClass(): Boolean = this.isObjCClass() &&
|
fun ClassDescriptor.isExternalObjCClass(): Boolean = this.isObjCClass() &&
|
||||||
this.parentsWithSelf.filterIsInstance<ClassDescriptor>().any {
|
this.parentsWithSelf.filterIsInstance<ClassDescriptor>().any {
|
||||||
@@ -78,10 +71,10 @@ fun ClassDescriptor.isObjCMetaClass(): Boolean = this.getAllSuperClassifiers().a
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun IrClass.isObjCMetaClass(): Boolean = selfOrAnySuperClass {
|
fun IrClass.isObjCMetaClass(): Boolean = selfOrAnySuperClass {
|
||||||
objCClassIdSignature == it.symbol.signature
|
it.hasEqualFqName(objCClassFqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrClass.isObjCProtocolClass(): Boolean = objCProtocolIdSignature == symbol.signature
|
fun IrClass.isObjCProtocolClass(): Boolean = hasEqualFqName(objCProtocolFqName)
|
||||||
|
|
||||||
fun ClassDescriptor.isObjCProtocolClass(): Boolean =
|
fun ClassDescriptor.isObjCProtocolClass(): Boolean =
|
||||||
this.fqNameSafe == objCProtocolFqName
|
this.fqNameSafe == objCProtocolFqName
|
||||||
@@ -123,9 +116,7 @@ private fun FunctionDescriptor.decodeObjCMethodAnnotation(): ObjCMethodInfo? {
|
|||||||
selector = it.getStringValue("selector"),
|
selector = it.getStringValue("selector"),
|
||||||
encoding = it.getStringValue("encoding"),
|
encoding = it.getStringValue("encoding"),
|
||||||
isStret = it.getArgumentValueOrNull<Boolean>("isStret") ?: false,
|
isStret = it.getArgumentValueOrNull<Boolean>("isStret") ?: false,
|
||||||
directSymbol = this.annotations.findAnnotation(objCDirectFqName)?.let {
|
directSymbol = this.annotations.findAnnotation(objCDirectFqName)?.getStringValue("symbol"),
|
||||||
it.getStringValue("symbol")
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4917,7 +4917,7 @@ standaloneTest("interop_opengl_teapot") {
|
|||||||
|
|
||||||
if (PlatformInfo.isAppleTarget(project)) {
|
if (PlatformInfo.isAppleTarget(project)) {
|
||||||
interopTest("interop_objc_smoke") {
|
interopTest("interop_objc_smoke") {
|
||||||
enabled = !isNoopGC && !isK2(project) // KT-56030
|
enabled = !isNoopGC
|
||||||
source = "interop/objc/smoke.kt"
|
source = "interop/objc/smoke.kt"
|
||||||
interop = 'objcSmoke'
|
interop = 'objcSmoke'
|
||||||
doBeforeBuild {
|
doBeforeBuild {
|
||||||
@@ -4968,7 +4968,7 @@ if (PlatformInfo.isAppleTarget(project)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interopTestMultifile("interop_objc_tests") {
|
interopTestMultifile("interop_objc_tests") {
|
||||||
disabled = isK2(project) // KT-55909
|
disabled = isK2(project) // KT-57504
|
||||||
source = "interop/objc/tests/"
|
source = "interop/objc/tests/"
|
||||||
interop = 'objcTests'
|
interop = 'objcTests'
|
||||||
flags = ['-tr', '-e', 'main']
|
flags = ['-tr', '-e', 'main']
|
||||||
@@ -5259,8 +5259,7 @@ if (PlatformInfo.isAppleTarget(project)) {
|
|||||||
|
|
||||||
standaloneTest("interop_kt55653") {
|
standaloneTest("interop_kt55653") {
|
||||||
// Test depends on macOS-specific AppKit
|
// Test depends on macOS-specific AppKit
|
||||||
enabled = (project.testTarget == 'macos_x64' || project.testTarget == 'macos_arm64' || project.testTarget == null) &&
|
enabled = (project.testTarget == 'macos_x64' || project.testTarget == 'macos_arm64' || project.testTarget == null)
|
||||||
!isK2(project) // KT-56030
|
|
||||||
source = "interop/objc/kt55653/main.kt"
|
source = "interop/objc/kt55653/main.kt"
|
||||||
useGoldenData = true
|
useGoldenData = true
|
||||||
UtilsKt.dependsOnPlatformLibs(it)
|
UtilsKt.dependsOnPlatformLibs(it)
|
||||||
|
|||||||
Reference in New Issue
Block a user