From 102b58b013df37747282ef94cf2370d33ad18eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Doln=C3=ADk?= Date: Fri, 12 Apr 2024 09:39:04 +0200 Subject: [PATCH] Refactor SirPhases to remove dependency on the Kotlin compiler. --- SKIE/acceptance-tests | 2 +- .../skie/util/directory/SkieBuildDirectory.kt | 3 - .../entrypoint/ObjectFilesPhaseInterceptor.kt | 10 +- ...portCodeSpecPhaseInterceptor.kgp_1.8.20.kt | 7 +- .../SkieCompilerConfigurationKeys.kt | 12 +- .../SimpleFunctionConfiguration.kt | 4 +- .../DescriptorConfigurationProvider.kt | 10 +- .../skie/context/ClassExportPhaseContext.kt | 7 +- .../DescriptorConversionPhaseContext.kt | 50 ++++ .../DescriptorModificationPhaseContext.kt | 4 +- .../touchlab/skie/context/InitPhaseContext.kt | 14 +- .../skie/context/KotlinIrPhaseContext.kt | 4 +- .../touchlab/skie/context/LinkPhaseContext.kt | 7 +- .../touchlab/skie/context/MainSkieContext.kt | 59 +++- .../touchlab/skie/context/SirPhaseContext.kt | 43 +-- .../skie/context/SymbolTablePhaseContext.kt | 4 +- .../skie/entrypoint/EntrypointUtils.kt | 19 +- .../co/touchlab/skie/kir/KirProvider.kt | 146 +++------- .../touchlab/skie/kir/KirProviderDelegate.kt | 16 ++ .../touchlab/skie/kir/builtin/KirBuiltins.kt | 220 ++++++++++----- .../kir/descriptor/DescriptorKirProvider.kt | 251 ++++++++++++++++++ .../kir/element/KirCallableDeclaration.kt | 7 +- .../co/touchlab/skie/kir/element/KirClass.kt | 70 ++--- .../skie/kir/element/KirConstructor.kt | 11 +- .../touchlab/skie/kir/element/KirEnumEntry.kt | 8 +- .../touchlab/skie/kir/element/KirFunction.kt | 12 +- .../co/touchlab/skie/kir/element/KirModule.kt | 8 +- .../touchlab/skie/kir/element/KirProperty.kt | 12 +- .../skie/kir/element/KirSimpleFunction.kt | 14 +- .../skie/kir/element/KirTypeParameter.kt | 10 +- .../skie/kir/element/KirValueParameter.kt | 30 +-- .../skie/kir/type/BlockPointerKirType.kt | 7 +- .../skie/kir/type/DeclarationBackedKirType.kt | 3 + .../touchlab/skie/kir/type/DeclaredKirType.kt | 8 + .../touchlab/skie/kir/type/ErrorOutKirType.kt | 3 - .../skie/kir/type/NonNullReferenceKirType.kt | 3 + .../skie/kir/type/NullableReferenceKirType.kt | 6 + .../touchlab/skie/kir/type/PointerKirType.kt | 6 + .../skie/kir/type/ReferenceKirType.kt | 4 +- .../skie/kir/type/SpecialOirKirType.kt | 5 + .../skie/kir/type/SuspendCompletionKirType.kt | 5 - .../kir/type/TypeParameterUsageKirType.kt | 7 + .../skie/kir/type/UnresolvedFlowKirType.kt | 9 + .../type/translation/KirCustomTypeMapper.kt | 15 ++ .../type/translation/KirCustomTypeMappers.kt} | 92 ++++--- .../KirDeclarationTypeTranslator.kt | 158 +++++++++++ .../type/translation/KirTypeParameterScope.kt | 85 ++++++ .../kir/type/translation/KirTypeTranslator.kt | 234 ++++++++-------- .../KirTypeTranslatorUtilityScope.kt | 31 +++ .../co/touchlab/skie/oir/OirProvider.kt | 85 +++--- .../touchlab/skie/oir/builtin/OirBuiltins.kt | 72 ----- .../co/touchlab/skie/oir/element/OirClass.kt | 15 +- .../type/translation/OirCustomTypeMapper.kt | 15 -- .../type/translation/OirTypeParameterScope.kt | 74 ------ .../oir/type/translation/OirTypeTranslator.kt | 210 +++------------ .../touchlab/skie/phases/BackgroundPhase.kt | 10 + .../touchlab/skie/phases/ClassExportPhase.kt | 7 +- .../touchlab/skie/phases/CommonSkieContext.kt | 41 +++ .../skie/phases/DescriptorConversionPhase.kt | 31 +++ .../phases/DescriptorModificationPhase.kt | 4 +- .../{SkiePhase.kt => ForegroundPhase.kt} | 21 +- .../co/touchlab/skie/phases/InitPhase.kt | 64 +---- .../co/touchlab/skie/phases/KotlinIrPhase.kt | 4 +- .../co/touchlab/skie/phases/LinkPhase.kt | 7 +- .../co/touchlab/skie/phases/ScheduledPhase.kt | 26 ++ .../co/touchlab/skie/phases/SirPhase.kt | 16 +- .../skie/phases/SkiePhaseScheduler.kt | 82 ++++-- .../touchlab/skie/phases/SymbolTablePhase.kt | 4 +- .../performance/SkiePerformanceAnalytics.kt | 2 +- .../apinotes/MoveBridgesToTopLevelPhase.kt | 2 +- .../apinotes/builder/ApiNotesFactory.kt | 4 +- ...erifyDescriptorProviderConsistencyPhase.kt | 8 +- .../DefaultArgumentGenerator.kt | 7 +- ...onflictingDefaultArgumentOverloadsPhase.kt | 2 +- .../BaseDefaultArgumentGeneratorDelegate.kt | 5 +- ...unctionDefaultArgumentGeneratorDelegate.kt | 25 +- ...ructorsDefaultArgumentGeneratorDelegate.kt | 43 ++- .../DefaultArgumentGeneratorDelegate.kt | 4 +- .../features/enums/EnumEntryRenamingPhase.kt | 18 +- .../enums/ExhaustiveEnumsGenerator.kt | 7 +- .../phases/features/flow/ConvertFlowsPhase.kt | 140 +++++----- .../features/flow/FlowMappingStrategy.kt | 27 +- .../phases/features/flow/SupportedFlow.kt | 3 + ...UnifyFlowConfigurationForOverridesPhase.kt | 12 +- .../FileScopeConversionParentProvider.kt | 4 +- .../features/functions/FileScopeConvertor.kt | 4 +- .../FileScopeConvertorDelegateScope.kt | 5 - ...erfaceExtensionMembersConvertorDelegate.kt | 8 +- .../SealedGeneratorExtensionContainer.kt | 3 +- .../features/sealed/SealedInteropGenerator.kt | 2 +- .../suspend/KotlinSuspendGeneratorDelegate.kt | 31 +-- .../features/suspend/SuspendGenerator.kt | 16 +- .../suspend/SwiftSuspendGeneratorDelegate.kt | 27 +- .../GenerateFakeObjCDependenciesPhase.kt | 2 +- .../phases/kir/CreateExposedKirTypesPhase.kt | 240 +++++++++++++++++ .../skie/phases/kir/CreateKirMembersPhase.kt | 243 ++++++++++++----- .../skie/phases/kir/CreateKirTypesPhase.kt | 162 ----------- ...ameConflictingCallableDeclarationsPhase.kt | 29 +- ...teropFrameworkNameForPlatformTypesPhase.kt | 30 +-- .../ConfigureExternalOirTypesBridgingPhase.kt | 2 +- .../phases/oir/CreateExternalOirTypesPhase.kt | 32 +++ .../oir/CreateFakeObjCConstructorsPhase.kt | 2 +- .../phases/oir/CreateKotlinOirTypesPhase.kt | 61 +++++ .../skie/phases/oir/CreateOirMembersPhase.kt | 38 +-- .../skie/phases/oir/CreateOirTypesPhase.kt | 105 -------- ...ixOirFunctionSignaturesForApiNotesPhase.kt | 2 +- .../oir/InitializeOirSuperTypesPhase.kt | 25 ++ .../oir/util/ExternalApiNotesProvider.kt | 3 +- .../ConfigureSwiftSpecificLinkerArgsPhase.kt | 24 ++ .../phases/other/ExtraClassExportPhase.kt | 13 +- .../FixDuplicatedOverriddenFunctionsPhase.kt | 4 +- .../other/ProcessReportedMessagesPhase.kt | 41 +++ .../other/VerifyNoBitcodeEmbeddingPhase.kt | 5 +- ...bleNameTypeAliasesForKotlinRuntimePhase.kt | 1 - .../runtime/KotlinRuntimeHidingPhase.kt | 5 +- .../member/CreateAsyncSirFunctionsPhase.kt | 2 +- .../sir/member/CreateSirMembersPhase.kt | 26 +- .../sir/member/InitializeSirOverridesPhase.kt | 2 +- ...ipKonanCallableDeclarationManglingPhase.kt | 8 +- .../sir/type/CreateExternalSirTypesPhase.kt | 9 +- .../type/CreateKotlinSirExtensionsPhase.kt | 2 +- .../sir/type/CreateKotlinSirTypesPhase.kt | 48 ++-- .../sir/type/CreateStableTypeAliasesPhase.kt | 2 +- ...ixNamesOfInaccessibleNestedClassesPhase.kt | 4 +- ...ase.kt => InitializeSirSuperTypesPhase.kt} | 2 +- .../skie/phases/swift/CompileSwiftPhase.kt | 88 +++--- .../swift/SwiftCompilerConfiguration.kt | 10 - ...RenameTypesConflictsWithOtherTypesPhase.kt | 21 +- ...ypesConflictingWithExternalModulesPhase.kt | 1 + .../skie/phases/util/SkiePhaseGroup.kt | 116 ++++---- .../util/StatefulDescriptorConversionPhase.kt | 5 + .../phases/util/StatefulScheduledPhase.kt | 20 ++ .../skie/phases/util/StatefulSirPhase.kt | 2 +- .../skie/phases/util/StatefulSkiePhase.kt | 42 --- .../skie/sir/ClassNamespaceProvider.kt | 24 +- .../co/touchlab/skie/sir/SirFileProvider.kt | 6 +- .../co/touchlab/skie/sir/SirProvider.kt | 24 +- .../skie/sir/type/SirDeclaredSirType.kt | 11 +- .../kotlin/co/touchlab/skie/util/Reporter.kt | 48 ++-- .../util/SirDeclaration+resolveCollision.kt | 18 +- .../skie/util/SwiftCompilerConfiguration.kt | 20 ++ .../skie/util/parallel/ParallelFlatMap.kt | 4 +- .../skie/util/parallel/ParallelMap.kt | 4 +- 143 files changed, 2612 insertions(+), 1978 deletions(-) create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/DescriptorConversionPhaseContext.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/KirProviderDelegate.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/descriptor/DescriptorKirProvider.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/DeclarationBackedKirType.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/DeclaredKirType.kt delete mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/ErrorOutKirType.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/NonNullReferenceKirType.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/NullableReferenceKirType.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/PointerKirType.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/SpecialOirKirType.kt delete mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/SuspendCompletionKirType.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/TypeParameterUsageKirType.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/UnresolvedFlowKirType.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirCustomTypeMapper.kt rename SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/{oir/type/translation/OirCustomTypeMappers.kt => kir/type/translation/KirCustomTypeMappers.kt} (56%) create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirDeclarationTypeTranslator.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeParameterScope.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeTranslatorUtilityScope.kt delete mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/builtin/OirBuiltins.kt delete mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirCustomTypeMapper.kt delete mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirTypeParameterScope.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/BackgroundPhase.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/CommonSkieContext.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/DescriptorConversionPhase.kt rename SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/{SkiePhase.kt => ForegroundPhase.kt} (76%) create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ScheduledPhase.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateExposedKirTypesPhase.kt delete mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateKirTypesPhase.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateExternalOirTypesPhase.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateKotlinOirTypesPhase.kt delete mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateOirTypesPhase.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/InitializeOirSuperTypesPhase.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ConfigureSwiftSpecificLinkerArgsPhase.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ProcessReportedMessagesPhase.kt rename SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/{InitializeSirTypesSuperTypesForOirPhase.kt => InitializeSirSuperTypesPhase.kt} (95%) delete mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/swift/SwiftCompilerConfiguration.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulDescriptorConversionPhase.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulScheduledPhase.kt delete mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulSkiePhase.kt create mode 100644 SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/SwiftCompilerConfiguration.kt diff --git a/SKIE/acceptance-tests b/SKIE/acceptance-tests index cbb18ff43..84a86f65b 160000 --- a/SKIE/acceptance-tests +++ b/SKIE/acceptance-tests @@ -1 +1 @@ -Subproject commit cbb18ff43e9e7bf13527ef0b50370b5710a2ea23 +Subproject commit 84a86f65bb51f8197a6a280f6012270ff32b090b diff --git a/SKIE/common/util/src/commonMain/kotlin/co/touchlab/skie/util/directory/SkieBuildDirectory.kt b/SKIE/common/util/src/commonMain/kotlin/co/touchlab/skie/util/directory/SkieBuildDirectory.kt index 14d14577c..347312f36 100644 --- a/SKIE/common/util/src/commonMain/kotlin/co/touchlab/skie/util/directory/SkieBuildDirectory.kt +++ b/SKIE/common/util/src/commonMain/kotlin/co/touchlab/skie/util/directory/SkieBuildDirectory.kt @@ -5,9 +5,6 @@ import co.touchlab.skie.util.directory.structure.PermanentDirectory import co.touchlab.skie.util.directory.structure.RootDirectory import co.touchlab.skie.util.directory.structure.TemporaryDirectory import java.io.File -import kotlin.io.path.isDirectory -import kotlin.io.path.listDirectoryEntries -import kotlin.io.path.name class SkieBuildDirectory( rootDirectory: File, diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_1.8.0/kotlin/co/touchlab/skie/entrypoint/ObjectFilesPhaseInterceptor.kt b/SKIE/compiler/kotlin-plugin/src/kgp_1.8.0/kotlin/co/touchlab/skie/entrypoint/ObjectFilesPhaseInterceptor.kt index 87dd38b1e..21b9846bd 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_1.8.0/kotlin/co/touchlab/skie/entrypoint/ObjectFilesPhaseInterceptor.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_1.8.0/kotlin/co/touchlab/skie/entrypoint/ObjectFilesPhaseInterceptor.kt @@ -19,11 +19,17 @@ internal class ObjectFilesPhaseInterceptor : SameTypePhaseInterceptor Unit) { val objCExportedInterface = context.objCExport.reflectedBy().exportedInterface as ObjCExportedInterface - EntrypointUtils.launchSirPhases( - mainSkieContext = context.config.configuration.mainSkieContext, + val mainSkieContext = context.config.configuration.mainSkieContext + + EntrypointUtils.runDescriptorConversionPhases( + mainSkieContext = mainSkieContext, objCExportedInterfaceProvider = ObjCExportedInterfaceProvider(objCExportedInterface), ) + EntrypointUtils.runSirPhases( + mainSkieContext = mainSkieContext, + ) + return next(context, input) } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_1.8.20..1.9.20/kotlin/co/touchlab/skie/entrypoint/CreateObjCExportCodeSpecPhaseInterceptor.kgp_1.8.20.kt b/SKIE/compiler/kotlin-plugin/src/kgp_1.8.20..1.9.20/kotlin/co/touchlab/skie/entrypoint/CreateObjCExportCodeSpecPhaseInterceptor.kgp_1.8.20.kt index feb2a5315..334d48be2 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_1.8.20..1.9.20/kotlin/co/touchlab/skie/entrypoint/CreateObjCExportCodeSpecPhaseInterceptor.kgp_1.8.20.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_1.8.20..1.9.20/kotlin/co/touchlab/skie/entrypoint/CreateObjCExportCodeSpecPhaseInterceptor.kgp_1.8.20.kt @@ -26,7 +26,12 @@ internal class CreateObjCExportCodeSpecPhaseInterceptor : PhaseInterceptor("InitSkiePhaseContext") + object InitPhaseContext : CompilerConfigurationKey("InitSkiePhaseContext") object MainContext : CompilerConfigurationKey("MainSkieContext") object SkieDirectories : CompilerConfigurationKey("SKIE directories") - - object SwiftCompiler { - - val swiftVersion = CompilerConfigurationKey("Swift version") - val additionalFlags = CompilerConfigurationKey>("Additional Swift compiler flags") - } } -var CompilerConfiguration.initPhaseContext: InitPhase.Context +var CompilerConfiguration.initPhaseContext: InitPhaseContext get() = getNotNull(SkieConfigurationKeys.InitPhaseContext) set(value) = put(SkieConfigurationKeys.InitPhaseContext, value) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/configuration/SimpleFunctionConfiguration.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/configuration/SimpleFunctionConfiguration.kt index b75546076..21f5e7186 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/configuration/SimpleFunctionConfiguration.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/configuration/SimpleFunctionConfiguration.kt @@ -1,6 +1,6 @@ package co.touchlab.skie.configuration -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.CommonSkieContext class SimpleFunctionConfiguration( parent: FileOrClassConfiguration, @@ -18,6 +18,6 @@ class SimpleFunctionConfiguration( } } -context(SkiePhase.Context) +context(CommonSkieContext) val SimpleFunctionConfiguration.isSuspendInteropEnabled: Boolean get() = SkieConfigurationFlag.Feature_CoroutinesInterop.isEnabled && this[SuspendInterop.Enabled] diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/configuration/provider/descriptor/DescriptorConfigurationProvider.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/configuration/provider/descriptor/DescriptorConfigurationProvider.kt index 4260ce7c5..9e15d6c33 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/configuration/provider/descriptor/DescriptorConfigurationProvider.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/configuration/provider/descriptor/DescriptorConfigurationProvider.kt @@ -9,7 +9,7 @@ import co.touchlab.skie.configuration.SimpleFunctionConfiguration import co.touchlab.skie.configuration.ValueParameterConfiguration import co.touchlab.skie.configuration.provider.ConfigurationProvider import co.touchlab.skie.configuration.provider.IdentifiedConfigurationTarget -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.ForegroundPhase import org.jetbrains.kotlin.backend.common.serialization.findPackage import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor @@ -138,19 +138,19 @@ class DescriptorConfigurationProvider( } } -context(SkiePhase.Context) +context(ForegroundPhase.Context) val ClassDescriptor.configuration: ClassConfiguration get() = descriptorConfigurationProvider.getConfiguration(this) -context(SkiePhase.Context) +context(ForegroundPhase.Context) val SimpleFunctionDescriptor.configuration: SimpleFunctionConfiguration get() = descriptorConfigurationProvider.getConfiguration(this) -context(SkiePhase.Context) +context(ForegroundPhase.Context) val ConstructorDescriptor.configuration: ConstructorConfiguration get() = descriptorConfigurationProvider.getConfiguration(this) -context(SkiePhase.Context) +context(ForegroundPhase.Context) val FunctionDescriptor.configuration: FunctionConfiguration get() = when (this) { is SimpleFunctionDescriptor -> configuration diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/ClassExportPhaseContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/ClassExportPhaseContext.kt index a4385295f..d34ed5e61 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/ClassExportPhaseContext.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/ClassExportPhaseContext.kt @@ -1,14 +1,17 @@ package co.touchlab.skie.context +import co.touchlab.skie.kir.descriptor.MutableDescriptorProvider import co.touchlab.skie.kir.irbuilder.impl.DeclarationBuilderImpl import co.touchlab.skie.phases.ClassExportPhase -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.ForegroundPhase class ClassExportPhaseContext( mainSkieContext: MainSkieContext, -) : ClassExportPhase.Context, SkiePhase.Context by mainSkieContext { +) : ClassExportPhase.Context, ForegroundPhase.Context by mainSkieContext { override val context: ClassExportPhaseContext = this + override val descriptorProvider: MutableDescriptorProvider = mainSkieContext.descriptorProvider + override val declarationBuilder: DeclarationBuilderImpl = mainSkieContext.declarationBuilder } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/DescriptorConversionPhaseContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/DescriptorConversionPhaseContext.kt new file mode 100644 index 000000000..73c6e1a2f --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/DescriptorConversionPhaseContext.kt @@ -0,0 +1,50 @@ +package co.touchlab.skie.context + +import co.touchlab.skie.kir.KirProvider +import co.touchlab.skie.kir.builtin.KirBuiltins +import co.touchlab.skie.kir.descriptor.DescriptorKirProvider +import co.touchlab.skie.kir.descriptor.ObjCExportedInterfaceProvider +import co.touchlab.skie.kir.type.translation.KirCustomTypeMappers +import co.touchlab.skie.kir.type.translation.KirDeclarationTypeTranslator +import co.touchlab.skie.kir.type.translation.KirTypeTranslator +import co.touchlab.skie.phases.DescriptorConversionPhase +import co.touchlab.skie.phases.ForegroundPhase +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer + +class DescriptorConversionPhaseContext( + mainSkieContext: MainSkieContext, + override val objCExportedInterfaceProvider: ObjCExportedInterfaceProvider, +) : DescriptorConversionPhase.Context, ForegroundPhase.Context by mainSkieContext { + + override val context: DescriptorConversionPhase.Context = this + + override val kirProvider: KirProvider = KirProvider(lazy { descriptorKirProvider }, rootConfiguration).also { + mainSkieContext.kirProvider = it + } + + override val descriptorKirProvider: DescriptorKirProvider = DescriptorKirProvider( + mainModuleDescriptor = mainSkieContext.mainModuleDescriptor, + kirProvider = kirProvider, + kotlinBuiltIns = kotlinBuiltins, + extraDescriptorBuiltins = extraDescriptorBuiltins, + namer = namer, + descriptorConfigurationProvider = descriptorConfigurationProvider, + rootConfiguration = rootConfiguration, + ).also { + mainSkieContext.descriptorKirProvider = it + } + + override val kirBuiltins: KirBuiltins = descriptorKirProvider.kirBuiltins + + private val kirCustomTypeMappers = KirCustomTypeMappers(kirBuiltins, lazy { kirTypeTranslator }) + + override val kirTypeTranslator: KirTypeTranslator = KirTypeTranslator(descriptorKirProvider, kirCustomTypeMappers) + + override val kirDeclarationTypeTranslator: KirDeclarationTypeTranslator = KirDeclarationTypeTranslator( + kirTypeTranslator = kirTypeTranslator, + kirBuiltins = kirBuiltins, + ) + + override val namer: ObjCExportNamer + get() = objCExportedInterfaceProvider.namer +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/DescriptorModificationPhaseContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/DescriptorModificationPhaseContext.kt index 10138bb78..ecf019305 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/DescriptorModificationPhaseContext.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/DescriptorModificationPhaseContext.kt @@ -2,11 +2,11 @@ package co.touchlab.skie.context import co.touchlab.skie.kir.irbuilder.impl.DeclarationBuilderImpl import co.touchlab.skie.phases.DescriptorModificationPhase -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.ForegroundPhase class DescriptorModificationPhaseContext( mainSkieContext: MainSkieContext, -) : DescriptorModificationPhase.Context, SkiePhase.Context by mainSkieContext { +) : DescriptorModificationPhase.Context, ForegroundPhase.Context by mainSkieContext { override val context: DescriptorModificationPhaseContext = this diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/InitPhaseContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/InitPhaseContext.kt index 4db60e366..2c4ec6e26 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/InitPhaseContext.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/InitPhaseContext.kt @@ -6,11 +6,9 @@ import co.touchlab.skie.compilerinject.compilerplugin.SkieConfigurationKeys import co.touchlab.skie.configuration.RootConfiguration import co.touchlab.skie.configuration.provider.CompilerSkieConfigurationData import co.touchlab.skie.configuration.provider.ConfigurationProvider -import co.touchlab.skie.configuration.provider.descriptor.DescriptorConfigurationProvider import co.touchlab.skie.phases.InitPhase import co.touchlab.skie.phases.SkiePhaseScheduler import co.touchlab.skie.phases.analytics.performance.SkiePerformanceAnalytics -import co.touchlab.skie.phases.swift.SwiftCompilerConfiguration import co.touchlab.skie.plugin.analytics.AnalyticsCollector import co.touchlab.skie.util.FrameworkLayout import co.touchlab.skie.util.Reporter @@ -35,18 +33,10 @@ class InitPhaseContext( CompilerSkieConfigurationData.deserialize(serializedUserConfiguration) } - private val configurationProvider = ConfigurationProvider(skieConfigurationData) + val configurationProvider = ConfigurationProvider(skieConfigurationData) override val rootConfiguration: RootConfiguration = configurationProvider.rootConfiguration - override val descriptorConfigurationProvider: DescriptorConfigurationProvider = DescriptorConfigurationProvider(configurationProvider) - - override val swiftCompilerConfiguration: SwiftCompilerConfiguration = SwiftCompilerConfiguration( - sourceFilesDirectory = skieDirectories.buildDirectory.swift.directory, - swiftVersion = compilerConfiguration.get(SkieConfigurationKeys.SwiftCompiler.swiftVersion, "5"), - additionalFlags = compilerConfiguration.getList(SkieConfigurationKeys.SwiftCompiler.additionalFlags), - ) - override val analyticsCollector: AnalyticsCollector = AnalyticsCollector( skieBuildDirectory = skieDirectories.buildDirectory, skieConfiguration = skieConfigurationData, @@ -54,7 +44,7 @@ class InitPhaseContext( override val skiePerformanceAnalyticsProducer: SkiePerformanceAnalytics.Producer = SkiePerformanceAnalytics.Producer(rootConfiguration) - override val reporter: Reporter = Reporter(compilerConfiguration) + override val reporter: Reporter = Reporter() override val framework: FrameworkLayout = run { val frameworkPath = compilerConfiguration.getNotNull(KonanConfigKeys.OUTPUT) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/KotlinIrPhaseContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/KotlinIrPhaseContext.kt index b13067622..535bd5210 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/KotlinIrPhaseContext.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/KotlinIrPhaseContext.kt @@ -4,8 +4,8 @@ package co.touchlab.skie.context import co.touchlab.skie.kir.irbuilder.impl.DeclarationBuilderImpl import co.touchlab.skie.kir.util.SkieSymbolTable +import co.touchlab.skie.phases.ForegroundPhase import co.touchlab.skie.phases.KotlinIrPhase -import co.touchlab.skie.phases.SkiePhase import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl import org.jetbrains.kotlin.backend.konan.serialization.KonanIrLinker @@ -16,7 +16,7 @@ class KotlinIrPhaseContext( mainSkieContext: MainSkieContext, override val moduleFragment: IrModuleFragment, override val pluginContext: IrPluginContext, -) : KotlinIrPhase.Context, SkiePhase.Context by mainSkieContext { +) : KotlinIrPhase.Context, ForegroundPhase.Context by mainSkieContext { override val context: KotlinIrPhaseContext = this diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/LinkPhaseContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/LinkPhaseContext.kt index 2043f61c2..f8d7e2b3e 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/LinkPhaseContext.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/LinkPhaseContext.kt @@ -1,16 +1,19 @@ package co.touchlab.skie.context +import co.touchlab.skie.kir.descriptor.DescriptorKirProvider +import co.touchlab.skie.phases.ForegroundPhase import co.touchlab.skie.phases.LinkPhase -import co.touchlab.skie.phases.SkiePhase import java.nio.file.Path class LinkPhaseContext( private val mainSkieContext: MainSkieContext, private val link: (additionalObjectFiles: List) -> Unit, -) : LinkPhase.Context, SkiePhase.Context by mainSkieContext { +) : LinkPhase.Context, ForegroundPhase.Context by mainSkieContext { override val context: LinkPhase.Context = this + override val descriptorKirProvider: DescriptorKirProvider = mainSkieContext.descriptorKirProvider + override fun link(additionalObjectFiles: List) { link.invoke(additionalObjectFiles) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/MainSkieContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/MainSkieContext.kt index f0d035348..02e59ef9c 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/MainSkieContext.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/MainSkieContext.kt @@ -2,11 +2,19 @@ package co.touchlab.skie.context +import co.touchlab.skie.configuration.provider.descriptor.DescriptorConfigurationProvider +import co.touchlab.skie.kir.KirProvider +import co.touchlab.skie.kir.descriptor.DescriptorKirProvider import co.touchlab.skie.kir.descriptor.MutableDescriptorProvider import co.touchlab.skie.kir.descriptor.NativeDescriptorProvider import co.touchlab.skie.kir.irbuilder.impl.DeclarationBuilderImpl +import co.touchlab.skie.phases.BackgroundPhase +import co.touchlab.skie.phases.ForegroundPhase import co.touchlab.skie.phases.InitPhase -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.ScheduledPhase +import co.touchlab.skie.phases.util.StatefulScheduledPhase +import co.touchlab.skie.util.SwiftCompilerConfiguration +import co.touchlab.skie.util.SwiftCompilerConfiguration.BuildType import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -14,25 +22,30 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import kotlinx.coroutines.plus +import org.jetbrains.kotlin.backend.konan.BitcodeEmbedding import org.jetbrains.kotlin.backend.konan.FrontendServices import org.jetbrains.kotlin.backend.konan.KonanConfig +import org.jetbrains.kotlin.backend.konan.KonanConfigKeys import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import java.util.Collections class MainSkieContext internal constructor( - initPhaseContext: InitPhase.Context, + initPhaseContext: InitPhaseContext, override val konanConfig: KonanConfig, frontendServices: FrontendServices, val mainModuleDescriptor: ModuleDescriptor, exportedDependencies: Collection, -) : SkiePhase.Context, InitPhase.Context by initPhaseContext { +) : ForegroundPhase.Context, BackgroundPhase.Context, InitPhase.Context by initPhaseContext { private val skieCoroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Default) + CoroutineExceptionHandler { _, _ -> - // Hide default stderr output because the exception is handled at the end of the job + // Hides default stderr output because the exception is handled at the end of the job } - private val jobs = mutableListOf() + private val jobs = Collections.synchronizedList(mutableListOf()) - override val context: SkiePhase.Context + private val statefulScheduledPhaseBodies = Collections.synchronizedMap(mutableMapOf, MutableList>()) + + override val context: MainSkieContext get() = this override val descriptorProvider: MutableDescriptorProvider = NativeDescriptorProvider( @@ -41,8 +54,27 @@ class MainSkieContext internal constructor( frontendServices = frontendServices, ) + override val descriptorConfigurationProvider: DescriptorConfigurationProvider = DescriptorConfigurationProvider(initPhaseContext.configurationProvider) + val declarationBuilder: DeclarationBuilderImpl = DeclarationBuilderImpl(mainModuleDescriptor, descriptorProvider) + lateinit var kirProvider: KirProvider + + lateinit var descriptorKirProvider: DescriptorKirProvider + + override val swiftCompilerConfiguration: SwiftCompilerConfiguration = SwiftCompilerConfiguration( + // TODO To SkieConfiguration via RootScope Key + swiftVersion = "5", + // TODO To SkieConfiguration via RootScope Key + additionalFlags = emptyList(), + buildType = if (konanConfig.debug) BuildType.Debug else BuildType.Release, + targetTriple = configurables.targetTriple, + bitcodeEmbeddingMode = compilerConfiguration[KonanConfigKeys.BITCODE_EMBEDDING_MODE] ?: BitcodeEmbedding.Mode.NONE, + absoluteTargetToolchainPath = configurables.absoluteTargetToolchain, + absoluteTargetSysRootPath = configurables.absoluteTargetSysRoot, + osVersionMin = configurables.osVersionMin, + ) + override fun launch(action: suspend () -> Unit) { val job = skieCoroutineScope.launch { action() @@ -51,6 +83,21 @@ class MainSkieContext internal constructor( jobs.add(job) } + override fun storeStatefulScheduledPhaseBody(phase: StatefulScheduledPhase, action: CONTEXT.() -> Unit) { + val bodies = statefulScheduledPhaseBodies.getOrPut(phase) { mutableListOf() } + + bodies.add(action) + } + + @Suppress("UNCHECKED_CAST") + override fun executeStatefulScheduledPhase(phase: StatefulScheduledPhase, context: CONTEXT) { + val phaseBodies = statefulScheduledPhaseBodies[phase] ?: return + + phaseBodies.forEach { phaseBody -> + (phaseBody as CONTEXT.() -> Unit).invoke(context) + } + } + suspend fun awaitAllBackgroundJobs() { jobs.joinAll() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/SirPhaseContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/SirPhaseContext.kt index 1ad939f08..a258fa193 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/SirPhaseContext.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/SirPhaseContext.kt @@ -2,74 +2,47 @@ package co.touchlab.skie.context import co.touchlab.skie.kir.KirProvider import co.touchlab.skie.kir.builtin.KirBuiltins -import co.touchlab.skie.kir.descriptor.ObjCExportedInterfaceProvider -import co.touchlab.skie.kir.type.translation.KirTypeTranslator import co.touchlab.skie.oir.OirProvider -import co.touchlab.skie.oir.builtin.OirBuiltins -import co.touchlab.skie.oir.type.translation.OirCustomTypeMappers import co.touchlab.skie.oir.type.translation.OirTypeTranslator +import co.touchlab.skie.phases.BackgroundPhase import co.touchlab.skie.phases.SirPhase -import co.touchlab.skie.phases.SkiePhase import co.touchlab.skie.phases.oir.util.ExternalApiNotesProvider import co.touchlab.skie.sir.ClassNamespaceProvider import co.touchlab.skie.sir.SirFileProvider import co.touchlab.skie.sir.SirProvider import co.touchlab.skie.sir.builtin.SirBuiltins import co.touchlab.skie.sir.type.translation.SirTypeTranslator -import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer class SirPhaseContext( mainSkieContext: MainSkieContext, - override val objCExportedInterfaceProvider: ObjCExportedInterfaceProvider, -) : SirPhase.Context, SkiePhase.Context by mainSkieContext { - - override val namer: ObjCExportNamer - get() = objCExportedInterfaceProvider.namer +) : SirPhase.Context, BackgroundPhase.Context by mainSkieContext { override val context: SirPhase.Context = this - override val kirProvider: KirProvider = KirProvider(kotlinBuiltins, extraDescriptorBuiltins, namer, rootConfiguration, descriptorConfigurationProvider) + override val kirProvider: KirProvider = mainSkieContext.kirProvider - override val oirProvider: OirProvider = OirProvider(kirProvider.skieModule, extraDescriptorBuiltins, kirProvider, namer) + override val oirProvider: OirProvider = OirProvider(kirProvider) - override val sirProvider: SirProvider = - SirProvider(framework, kirProvider, oirProvider, descriptorConfigurationProvider, rootConfiguration, skieBuildDirectory) + override val sirProvider: SirProvider = SirProvider(framework, oirProvider, skieBuildDirectory, rootConfiguration) override val sirFileProvider: SirFileProvider = sirProvider.fileProvider override val kirBuiltins: KirBuiltins = kirProvider.kirBuiltins - override val oirBuiltins: OirBuiltins = oirProvider.oirBuiltins - override val sirBuiltins: SirBuiltins = sirProvider.sirBuiltins override val classNamespaceProvider: ClassNamespaceProvider = ClassNamespaceProvider( kirProvider = kirProvider, + oirProvider = oirProvider, sirProvider = sirProvider, - mainModuleDescriptor = mainSkieContext.mainModuleDescriptor, ) override val externalApiNotesProvider: ExternalApiNotesProvider = ExternalApiNotesProvider( - sdkPath = configurables.absoluteTargetSysRoot, + sdkPath = swiftCompilerConfiguration.absoluteTargetSysRootPath, sirProvider = sirProvider, ) - override val kirTypeTranslator: KirTypeTranslator = KirTypeTranslator() - - override val oirTypeTranslator: OirTypeTranslator by lazy { - OirTypeTranslator( - kirProvider = kirProvider, - oirProvider = oirProvider, - oirBuiltins = oirBuiltins, - customTypeMappers = OirCustomTypeMappers( - kirBuiltins = kirBuiltins, - oirBuiltins = oirBuiltins, - translator = lazy { - oirTypeTranslator - }, - ), - ) - } + override val oirTypeTranslator: OirTypeTranslator = OirTypeTranslator() override val sirTypeTranslator: SirTypeTranslator = SirTypeTranslator(sirBuiltins) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/SymbolTablePhaseContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/SymbolTablePhaseContext.kt index 0bff57a46..5a9bb1368 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/SymbolTablePhaseContext.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/context/SymbolTablePhaseContext.kt @@ -2,14 +2,14 @@ package co.touchlab.skie.context import co.touchlab.skie.kir.irbuilder.impl.DeclarationBuilderImpl import co.touchlab.skie.kir.util.SkieSymbolTable -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.ForegroundPhase import co.touchlab.skie.phases.SymbolTablePhase import org.jetbrains.kotlin.ir.util.SymbolTable class SymbolTablePhaseContext( mainSkieContext: MainSkieContext, symbolTable: SymbolTable, -) : SymbolTablePhase.Context, SkiePhase.Context by mainSkieContext { +) : SymbolTablePhase.Context, ForegroundPhase.Context by mainSkieContext { override val context: SymbolTablePhaseContext = this diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/entrypoint/EntrypointUtils.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/entrypoint/EntrypointUtils.kt index 19387f3ce..95439185e 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/entrypoint/EntrypointUtils.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/entrypoint/EntrypointUtils.kt @@ -4,14 +4,15 @@ package co.touchlab.skie.entrypoint import co.touchlab.skie.compilerinject.compilerplugin.mainSkieContext import co.touchlab.skie.context.ClassExportPhaseContext +import co.touchlab.skie.context.DescriptorConversionPhaseContext import co.touchlab.skie.context.DescriptorModificationPhaseContext +import co.touchlab.skie.context.InitPhaseContext import co.touchlab.skie.context.KotlinIrPhaseContext import co.touchlab.skie.context.LinkPhaseContext import co.touchlab.skie.context.MainSkieContext import co.touchlab.skie.context.SirPhaseContext import co.touchlab.skie.context.SymbolTablePhaseContext import co.touchlab.skie.kir.descriptor.ObjCExportedInterfaceProvider -import co.touchlab.skie.phases.InitPhase import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.konan.FrontendServices import org.jetbrains.kotlin.backend.konan.KonanConfig @@ -23,7 +24,7 @@ import java.nio.file.Path internal object EntrypointUtils { fun createMainSkieContext( - initPhaseContext: InitPhase.Context, + initPhaseContext: InitPhaseContext, konanConfig: KonanConfig, frontendServices: FrontendServices, mainModuleDescriptor: ModuleDescriptor, @@ -86,10 +87,18 @@ internal object EntrypointUtils { } } - fun launchSirPhases(mainSkieContext: MainSkieContext, objCExportedInterfaceProvider: ObjCExportedInterfaceProvider) { + fun runDescriptorConversionPhases(mainSkieContext: MainSkieContext, objCExportedInterfaceProvider: ObjCExportedInterfaceProvider) { with(mainSkieContext) { - skiePhaseScheduler.launchSirPhases { - SirPhaseContext(mainSkieContext, objCExportedInterfaceProvider) + skiePhaseScheduler.runDescriptorConversionPhases { + DescriptorConversionPhaseContext(mainSkieContext, objCExportedInterfaceProvider) + } + } + } + + fun runSirPhases(mainSkieContext: MainSkieContext) { + with(mainSkieContext) { + skiePhaseScheduler.runSirPhases { + SirPhaseContext(mainSkieContext) } } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/KirProvider.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/KirProvider.kt index 02a203f55..9048fb6ff 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/KirProvider.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/KirProvider.kt @@ -1,10 +1,7 @@ package co.touchlab.skie.kir -import co.touchlab.skie.configuration.ModuleConfiguration import co.touchlab.skie.configuration.RootConfiguration -import co.touchlab.skie.configuration.provider.descriptor.DescriptorConfigurationProvider import co.touchlab.skie.kir.builtin.KirBuiltins -import co.touchlab.skie.kir.descriptor.ExtraDescriptorBuiltins import co.touchlab.skie.kir.element.KirCallableDeclaration import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.kir.element.KirConstructor @@ -14,109 +11,74 @@ import co.touchlab.skie.kir.element.KirModule import co.touchlab.skie.kir.element.KirOverridableDeclaration import co.touchlab.skie.kir.element.KirProject import co.touchlab.skie.kir.element.KirSimpleFunction -import co.touchlab.skie.kir.element.classDescriptorOrNull -import co.touchlab.skie.kir.element.sourceFileOrNull -import co.touchlab.skie.phases.runtime.isSkieKotlinRuntime import co.touchlab.skie.sir.element.SirCallableDeclaration import co.touchlab.skie.sir.element.SirProperty -import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.SourceFile -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.descriptorUtil.module class KirProvider( - kotlinBuiltIns: KotlinBuiltIns, - extraDescriptorBuiltins: ExtraDescriptorBuiltins, - namer: ObjCExportNamer, - private val rootConfiguration: RootConfiguration, - private val descriptorConfigurationProvider: DescriptorConfigurationProvider, + delegate: Lazy, + rootConfiguration: RootConfiguration, ) { - private val modulesMap = mutableMapOf() - - private lateinit var classDescriptorCache: Map - private lateinit var fileCache: Map - private lateinit var fqNameCache: Map - private lateinit var descriptorsToCallableDeclarationsCache: Map> - private lateinit var sirToCallableDeclarationsCache: Map> private lateinit var sirToEnumEntryCache: Map - val allModules: Collection - get() = modulesMap.values + private val delegate by delegate + + val kotlinModules: Collection + get() = delegate.kotlinModules + + val allExternalClasses: Collection + get() = delegate.allExternalClassesAndProtocols - lateinit var allClasses: Set + val allPlatformClasses: Collection + get() = delegate.allExternalClassesAndProtocols.filter { it.origin == KirClass.Origin.PlatformType } + + val allClasses: Set + get() = kotlinClasses + allExternalClasses + + lateinit var kotlinClasses: Set private set - lateinit var allEnums: Set + lateinit var kotlinEnums: Set private set - lateinit var allCallableDeclarations: List> + lateinit var kotlinCallableDeclarations: List> private set - lateinit var allFunctions: List> + lateinit var kotlinFunctions: List> private set - lateinit var allSimpleFunctions: List + lateinit var kotlinSimpleFunctions: List private set - lateinit var allConstructors: List + lateinit var kotlinConstructors: List private set - lateinit var allOverridableDeclaration: List> + lateinit var kotlinOverridableDeclaration: List> private set val project = KirProject(rootConfiguration) - val skieModule = getModule("Skie") - - private val stdlibModule = getModule(kotlinBuiltIns.string.module) - - val kirBuiltins: KirBuiltins = KirBuiltins( - stdlibModule = stdlibModule, - kotlinBuiltIns = kotlinBuiltIns, - extraDescriptorBuiltins = extraDescriptorBuiltins, - namer = namer, - descriptorConfigurationProvider = descriptorConfigurationProvider, - ) - - private fun getModule(name: String, descriptor: ModuleDescriptor? = null): KirModule = - modulesMap.getOrPut(name) { - KirModule( - name = name, - project = project, - descriptor = descriptor, - isSkieKotlinRuntime = descriptor?.isSkieKotlinRuntime ?: false, - configuration = descriptor?.let { descriptorConfigurationProvider.getConfiguration(it) } ?: ModuleConfiguration(rootConfiguration), - ) - } + val kirBuiltins: KirBuiltins + get() = delegate.kirBuiltins - fun getModule(moduleDescriptor: ModuleDescriptor): KirModule = - getModule((moduleDescriptor.stableName ?: moduleDescriptor.name).asStringStripSpecialMarkers(), moduleDescriptor) + val stdlibModule: KirModule + get() = delegate.stdlibModule - fun initializeClassCache() { + fun initializeKotlinClassCache() { val visitedClasses = mutableSetOf() - allModules.flatMap { it.classes }.forEach { + kotlinModules.flatMap { it.classes }.forEach { cacheClassesRecursively(it, visitedClasses) } - allClasses = visitedClasses.toSet() - allEnums = allClasses.filter { it.kind == KirClass.Kind.Enum }.toSet() - - classDescriptorCache = allClasses.mapNotNull { kirClass -> kirClass.classDescriptorOrNull?.let { it to kirClass } }.toMap() - fileCache = allClasses.mapNotNull { kirClass -> kirClass.sourceFileOrNull?.let { it to kirClass } }.toMap() + kotlinClasses = visitedClasses.toSet() + kotlinEnums = kotlinClasses.filter { it.kind == KirClass.Kind.Enum }.toSet() - fqNameCache = classDescriptorCache.mapKeys { it.key.fqNameSafe.asString() } + fqNameCache = kotlinClasses.associateBy { it.kotlinFqName } } private fun cacheClassesRecursively(kirClass: KirClass, visitedClasses: MutableSet) { @@ -126,49 +88,25 @@ class KirProvider( } fun initializeCallableDeclarationsCache() { - descriptorsToCallableDeclarationsCache = allClasses.flatMap { it.callableDeclarations }.associateBy { it.descriptor } + kotlinCallableDeclarations = kotlinClasses.flatMap { it.callableDeclarations } - allCallableDeclarations = descriptorsToCallableDeclarationsCache.values.toList() - - allFunctions = allCallableDeclarations.filterIsInstance>() - allSimpleFunctions = allFunctions.filterIsInstance() - allConstructors = allFunctions.filterIsInstance() - allOverridableDeclaration = allCallableDeclarations.filterIsInstance>() + kotlinFunctions = kotlinCallableDeclarations.filterIsInstance>() + kotlinSimpleFunctions = kotlinFunctions.filterIsInstance() + kotlinConstructors = kotlinFunctions.filterIsInstance() + kotlinOverridableDeclaration = kotlinCallableDeclarations.filterIsInstance>() } fun initializeSirCallableDeclarationsCache() { - sirToCallableDeclarationsCache = allCallableDeclarations.associateBy { it.originalSirDeclaration } + - allCallableDeclarations.filter { it.bridgedSirDeclaration != null }.associateBy { it.bridgedSirDeclaration!! } + sirToCallableDeclarationsCache = kotlinCallableDeclarations.associateBy { it.originalSirDeclaration } + + kotlinCallableDeclarations.filter { it.bridgedSirDeclaration != null }.associateBy { it.bridgedSirDeclaration!! } - sirToEnumEntryCache = allEnums.flatMap { it.enumEntries }.associateBy { it.sirEnumEntry } + sirToEnumEntryCache = kotlinEnums.flatMap { it.enumEntries }.associateBy { it.sirEnumEntry } } - fun getClass(classDescriptor: ClassDescriptor): KirClass = - findClass(classDescriptor) - ?: error("Class not found: $classDescriptor. This error usually means that the class is not exposed to Objective-C.") - - fun getClass(sourceFile: SourceFile): KirClass = - findClass(sourceFile) - ?: error("Class not found: $sourceFile. This error usually means that the class is not exposed to Objective-C.") - fun getClassByFqName(fqName: String): KirClass = findClassByFqName(fqName) ?: error("Class not found: $fqName. This error usually means that the class is not exposed to Objective-C.") - fun getFunction(functionDescriptor: FunctionDescriptor): KirSimpleFunction = - findFunction(functionDescriptor) - ?: error("Function not found: $functionDescriptor. This error usually means that the function is not exposed to Objective-C.") - - fun getConstructor(constructorDescriptor: ClassConstructorDescriptor): KirConstructor = - findConstructor(constructorDescriptor) - ?: error("Constructor not found: $constructorDescriptor. This error usually means that the constructor is not exposed to Objective-C.") - - fun findClass(classDescriptor: ClassDescriptor): KirClass? = - classDescriptorCache[classDescriptor.original] - - fun findClass(sourceFile: SourceFile): KirClass? = - fileCache[sourceFile] - fun findClassByFqName(fqName: String): KirClass? = fqNameCache[fqName] @@ -176,12 +114,6 @@ class KirProvider( fun findCallableDeclaration(callableDeclaration: SirCallableDeclaration): KirCallableDeclaration? = sirToCallableDeclarationsCache[callableDeclaration] as KirCallableDeclaration? - fun findFunction(functionDescriptor: FunctionDescriptor): KirSimpleFunction? = - descriptorsToCallableDeclarationsCache[functionDescriptor] as? KirSimpleFunction - - fun findConstructor(constructorDescriptor: ClassConstructorDescriptor): KirConstructor? = - descriptorsToCallableDeclarationsCache[constructorDescriptor] as? KirConstructor - fun findEnumEntry(property: SirProperty): KirEnumEntry? = sirToEnumEntryCache[property] } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/KirProviderDelegate.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/KirProviderDelegate.kt new file mode 100644 index 000000000..be9c17181 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/KirProviderDelegate.kt @@ -0,0 +1,16 @@ +package co.touchlab.skie.kir + +import co.touchlab.skie.kir.builtin.KirBuiltins +import co.touchlab.skie.kir.element.KirClass +import co.touchlab.skie.kir.element.KirModule + +interface KirProviderDelegate { + + val kotlinModules: Collection + + val stdlibModule: KirModule + + val kirBuiltins: KirBuiltins + + val allExternalClassesAndProtocols: Collection +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/builtin/KirBuiltins.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/builtin/KirBuiltins.kt index 36ffa6327..337b6baee 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/builtin/KirBuiltins.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/builtin/KirBuiltins.kt @@ -3,125 +3,225 @@ package co.touchlab.skie.kir.builtin import co.touchlab.skie.configuration.provider.descriptor.DescriptorConfigurationProvider +import co.touchlab.skie.kir.descriptor.DescriptorKirProvider import co.touchlab.skie.kir.descriptor.ExtraDescriptorBuiltins import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.kir.element.KirModule import co.touchlab.skie.kir.element.KirTypeParameter -import co.touchlab.skie.kir.type.ReferenceKirType +import co.touchlab.skie.kir.element.toTypeParameterUsage +import co.touchlab.skie.kir.type.DeclaredKirType +import co.touchlab.skie.oir.element.OirTypeParameter import org.jetbrains.kotlin.backend.konan.objcexport.NSNumberKind import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.KotlinTypeFactory -import org.jetbrains.kotlin.types.TypeProjectionImpl -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @Suppress("PropertyName", "FunctionName") class KirBuiltins( val stdlibModule: KirModule, - private val kotlinBuiltIns: KotlinBuiltIns, - private val extraDescriptorBuiltins: ExtraDescriptorBuiltins, + kotlinBuiltIns: KotlinBuiltIns, + extraDescriptorBuiltins: ExtraDescriptorBuiltins, private val namer: ObjCExportNamer, private val descriptorConfigurationProvider: DescriptorConfigurationProvider, + private val descriptorKirProvider: DescriptorKirProvider, ) { - // TODO Not all Builtin methods are not supported yet (supported are only those converted from Kotlin equivalents in Any) + // TODO Not all Builtin methods are supported yet (supported are only those converted from Kotlin equivalents in Any) - val Base by Class( + val NSObject: KirClass = Class(extraDescriptorBuiltins.NSObject) + + val NSCopying: KirClass = Class(extraDescriptorBuiltins.NSCopying) + + val NSError: KirClass = Class(extraDescriptorBuiltins.NSError) { + superTypes.add(NSObject.defaultType) + } + + val NSString: KirClass = Class(extraDescriptorBuiltins.NSString) { + superTypes.add(NSObject.defaultType) + } + + val NSArray: KirClass = Class(extraDescriptorBuiltins.NSArray) { + KirTypeParameter( + name = "ObjectType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) + + superTypes.add(NSObject.defaultType) + } + + val NSMutableArray: KirClass = Class(extraDescriptorBuiltins.NSMutableArray) { + val typeParameter = KirTypeParameter( + name = "ObjectType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) + + val typeArgument = typeParameter.toTypeParameterUsage() + + superTypes.add( + NSArray.toType(typeArgument), + ) + } + + val NSSet: KirClass = Class(extraDescriptorBuiltins.NSSet) { + KirTypeParameter( + name = "ObjectType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) + + superTypes.add(NSObject.defaultType) + } + + val NSMutableSet: KirClass = Class(extraDescriptorBuiltins.NSMutableSet) { + val typeParameter = KirTypeParameter( + name = "ObjectType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) + + val typeArgument = typeParameter.toTypeParameterUsage() + + superTypes.add( + NSSet.toType(typeArgument), + ) + } + + val NSDictionary: KirClass = Class(extraDescriptorBuiltins.NSDictionary) { + KirTypeParameter( + name = "KeyType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) + + KirTypeParameter( + name = "ObjectType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) + + superTypes.add(NSObject.defaultType) + } + + val NSMutableDictionary: KirClass = Class(extraDescriptorBuiltins.NSMutableDictionary) { + val keyTypeParameter = KirTypeParameter( + name = "KeyType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) + + val valueTypeParameter = KirTypeParameter( + name = "ObjectType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) + + val keyTypeArgument = keyTypeParameter.toTypeParameterUsage() + val valueTypeArgument = valueTypeParameter.toTypeParameterUsage() + + superTypes.add( + NSDictionary.toType(keyTypeArgument, valueTypeArgument), + ) + } + + val NSNumber: KirClass = Class(extraDescriptorBuiltins.NSNumber) { + // Technically should be NSValue instead but for our purposes it's not needed because we use the class only as a supertype + superTypes.add(NSObject.defaultType) + } + + val Base: KirClass = Class( name = namer.kotlinAnyName, classDescriptor = kotlinBuiltIns.any, superTypes = listOf( - extraDescriptorBuiltins.NSObject.defaultType, - extraDescriptorBuiltins.NSCopying.defaultType, + NSObject.defaultType, + NSCopying.defaultType, ), ) - val MutableSet by Class( + val MutableSet: KirClass = Class( name = namer.mutableSetName, classDescriptor = kotlinBuiltIns.mutableSet, ) { - val typeArgument = TypeProjectionImpl(kotlinBuiltIns.mutableSet.declaredTypeParameters.single().defaultType) + val typeParameter = KirTypeParameter( + name = "ObjectType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) - val kotlinSuperType = KotlinTypeFactory.simpleType(extraDescriptorBuiltins.NSMutableSet.defaultType, arguments = listOf(typeArgument)) + val typeArgument = typeParameter.toTypeParameterUsage() superTypes.add( - ReferenceKirType(kotlinSuperType), + NSMutableSet.toType(typeArgument), ) } - val MutableMap: KirClass by Class( + val MutableMap: KirClass = Class( name = namer.mutableMapName, classDescriptor = kotlinBuiltIns.mutableMap, ) { - val keyArgument = TypeProjectionImpl(kotlinBuiltIns.mutableMap.declaredTypeParameters[0].defaultType) - val valueArgument = TypeProjectionImpl(kotlinBuiltIns.mutableMap.declaredTypeParameters[1].defaultType) + val keyTypeParameter = KirTypeParameter( + name = "KeyType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, + ) - val kotlinSuperType = KotlinTypeFactory.simpleType( - baseType = extraDescriptorBuiltins.NSMutableDictionary.defaultType, - arguments = listOf(keyArgument, valueArgument), + val valueTypeParameter = KirTypeParameter( + name = "ObjectType", + parent = this, + variance = OirTypeParameter.Variance.Covariant, ) + val keyTypeArgument = keyTypeParameter.toTypeParameterUsage() + val valueTypeArgument = valueTypeParameter.toTypeParameterUsage() + superTypes.add( - ReferenceKirType(kotlinSuperType), + NSMutableDictionary.toType(keyTypeArgument, valueTypeArgument), ) } - val Number: KirClass by Class( + val Number: KirClass = Class( name = namer.kotlinNumberName, classDescriptor = kotlinBuiltIns.number, superTypes = listOf( - extraDescriptorBuiltins.NSNumber.defaultType, + NSNumber.defaultType, ), ) val nsNumberDeclarations: Map = NSNumberKind.values().mapNotNull { it.mappedKotlinClassId } .associateWith { classId -> - val descriptor = kotlinBuiltIns.getBuiltInClassByFqName(FqName(classId.asFqNameString())) - - KirClass( - descriptor = KirClass.Descriptor.Class(descriptor), + Class( name = namer.numberBoxName(classId), - parent = stdlibModule, - kind = KirClass.Kind.Class, - superTypes = listOf(kotlinBuiltIns.numberType).map(::ReferenceKirType), - isSealed = false, - hasUnexposedSealedSubclasses = false, - belongsToSkieKotlinRuntime = false, - configuration = descriptorConfigurationProvider.getConfiguration(descriptor), + classDescriptor = kotlinBuiltIns.getBuiltInClassByFqName(FqName(classId.asFqNameString())), + superTypes = listOf(Number.defaultType), ) } private fun Class( name: ObjCExportNamer.ClassOrProtocolName, classDescriptor: ClassDescriptor, - superTypes: List = emptyList(), + superTypes: List = emptyList(), apply: KirClass.() -> Unit = {}, - ): ReadOnlyProperty = - object : ReadOnlyProperty { - - private val value = KirClass( - descriptor = KirClass.Descriptor.Class(classDescriptor), - name = name, - parent = stdlibModule, - kind = KirClass.Kind.Class, - superTypes = superTypes.map(::ReferenceKirType), - isSealed = false, - hasUnexposedSealedSubclasses = false, - belongsToSkieKotlinRuntime = false, - configuration = descriptorConfigurationProvider.getConfiguration(classDescriptor), - ).apply { - classDescriptor.declaredTypeParameters.forEach { typeParameter -> - KirTypeParameter(typeParameter, this) - } - - apply() - } + ): KirClass = KirClass( + kotlinFqName = classDescriptor.fqNameSafe.asString(), + objCName = name.objCName, + swiftName = name.swiftName, + parent = stdlibModule, + kind = KirClass.Kind.Class, + origin = KirClass.Origin.Kotlin, + superTypes = superTypes, + isSealed = false, + hasUnexposedSealedSubclasses = false, + configuration = descriptorConfigurationProvider.getConfiguration(classDescriptor), + ).apply { + descriptorKirProvider.registerClass(this, classDescriptor) + + apply() + } - override fun getValue(thisRef: Any?, property: KProperty<*>): KirClass = - value - } + fun Class(descriptor: ClassDescriptor, apply: KirClass.() -> Unit = {}): KirClass = + descriptorKirProvider.getExternalBuiltinClass(descriptor).apply(apply) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/descriptor/DescriptorKirProvider.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/descriptor/DescriptorKirProvider.kt new file mode 100644 index 000000000..248b1d088 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/descriptor/DescriptorKirProvider.kt @@ -0,0 +1,251 @@ +package co.touchlab.skie.kir.descriptor + +import co.touchlab.skie.configuration.ClassConfiguration +import co.touchlab.skie.configuration.FileConfiguration +import co.touchlab.skie.configuration.FileOrClassConfiguration +import co.touchlab.skie.configuration.ModuleConfiguration +import co.touchlab.skie.configuration.PackageConfiguration +import co.touchlab.skie.configuration.RootConfiguration +import co.touchlab.skie.configuration.provider.descriptor.DescriptorConfigurationProvider +import co.touchlab.skie.kir.KirProvider +import co.touchlab.skie.kir.KirProviderDelegate +import co.touchlab.skie.kir.builtin.KirBuiltins +import co.touchlab.skie.kir.element.KirCallableDeclaration +import co.touchlab.skie.kir.element.KirClass +import co.touchlab.skie.kir.element.KirConstructor +import co.touchlab.skie.kir.element.KirElement +import co.touchlab.skie.kir.element.KirEnumEntry +import co.touchlab.skie.kir.element.KirModule +import co.touchlab.skie.kir.element.KirSimpleFunction +import co.touchlab.skie.kir.element.KirTypeParameter +import co.touchlab.skie.kir.element.KirValueParameter +import co.touchlab.skie.phases.runtime.belongsToSkieKotlinRuntime +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.ParameterDescriptor +import org.jetbrains.kotlin.descriptors.SourceFile +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.isInterface +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +class DescriptorKirProvider( + private val mainModuleDescriptor: ModuleDescriptor, + private val kirProvider: KirProvider, + kotlinBuiltIns: KotlinBuiltIns, + extraDescriptorBuiltins: ExtraDescriptorBuiltins, + namer: ObjCExportNamer, + private val descriptorConfigurationProvider: DescriptorConfigurationProvider, + rootConfiguration: RootConfiguration, +) : KirProviderDelegate { + + private val kotlinModulesMap = mutableMapOf() + + private val kirElementToDescriptorCache = mutableMapOf() + + private val classDescriptorToKirCache = mutableMapOf() + private val kirToClassDescriptorCache = mutableMapOf() + + private val sourceFileToKirCache = mutableMapOf() + private val kirToSourceFileCache = mutableMapOf() + + private val callableDeclarationDescriptorToKirCache = mutableMapOf>() + private val kirToCallableDeclarationDescriptorCache = mutableMapOf, CallableMemberDescriptor>() + + private val typeParameterToDescriptorsCache = mutableMapOf() + + private val kirToValueParameterDescriptorsCache = mutableMapOf() + + override val allExternalClassesAndProtocols: Collection + get() = externalClassesAndProtocolsCache.values + + private val externalClassesAndProtocolsCache = mutableMapOf() + + override val kotlinModules: Collection + get() = kotlinModulesMap.values + + private val externalModule: KirModule = KirModule( + name = "", + project = kirProvider.project, + configuration = ModuleConfiguration(rootConfiguration), + origin = KirModule.Origin.External, + ) + + override val stdlibModule: KirModule = getKotlinModule(kotlinBuiltIns.string.module) + + private val externalClassConfiguration = ClassConfiguration( + FileOrClassConfiguration.File(FileConfiguration(PackageConfiguration(externalModule.configuration))), + ) + + override val kirBuiltins: KirBuiltins = KirBuiltins( + stdlibModule = this.stdlibModule, + kotlinBuiltIns = kotlinBuiltIns, + extraDescriptorBuiltins = extraDescriptorBuiltins, + namer = namer, + descriptorKirProvider = this, + descriptorConfigurationProvider = descriptorConfigurationProvider, + ) + + fun getKotlinModule(moduleDescriptor: ModuleDescriptor): KirModule { + val name = (moduleDescriptor.stableName ?: moduleDescriptor.name).asStringStripSpecialMarkers() + + return kotlinModulesMap.getOrPut(name) { + KirModule( + name = name, + project = kirProvider.project, + configuration = descriptorConfigurationProvider.getConfiguration(moduleDescriptor), + origin = when { + moduleDescriptor.belongsToSkieKotlinRuntime -> KirModule.Origin.SkieRuntime + moduleDescriptor == mainModuleDescriptor -> KirModule.Origin.SkieGenerated + else -> KirModule.Origin.Kotlin + }, + ) + } + } + + fun registerClass(kirClass: KirClass, classDescriptor: ClassDescriptor) { + kirElementToDescriptorCache[kirClass] = classDescriptor.original + + classDescriptorToKirCache[classDescriptor.original] = kirClass + kirToClassDescriptorCache[kirClass] = classDescriptor.original + } + + fun registerFile(kirClass: KirClass, sourceFile: SourceFile) { + sourceFileToKirCache[sourceFile] = kirClass + kirToSourceFileCache[kirClass] = sourceFile + } + + fun registerCallableDeclaration(callableDeclaration: KirCallableDeclaration<*>, callableMemberDescriptor: CallableMemberDescriptor) { + kirElementToDescriptorCache[callableDeclaration] = callableMemberDescriptor.original + + callableDeclarationDescriptorToKirCache[callableMemberDescriptor.original] = callableDeclaration + kirToCallableDeclarationDescriptorCache[callableDeclaration] = callableMemberDescriptor.original + } + + fun registerTypeParameter(typeParameter: KirTypeParameter, typeParameterDescriptor: TypeParameterDescriptor) { + kirElementToDescriptorCache[typeParameter] = typeParameterDescriptor.original + + typeParameterToDescriptorsCache[typeParameter] = typeParameterDescriptor.original + } + + fun registerValueParameter(valueParameter: KirValueParameter, parameterDescriptor: ParameterDescriptor) { + kirElementToDescriptorCache[valueParameter] = parameterDescriptor.original + + kirToValueParameterDescriptorsCache[parameterDescriptor.original] = valueParameter + } + + fun registerEnumEntry(kirEnumEntry: KirEnumEntry, classDescriptor: ClassDescriptor) { + kirElementToDescriptorCache[kirEnumEntry] = classDescriptor.original + } + + fun getClass(classDescriptor: ClassDescriptor): KirClass = + findClass(classDescriptor) + ?: error("Class not found: $classDescriptor. This error usually means that the class is not exposed to Objective-C.") + + fun getClass(sourceFile: SourceFile): KirClass = + findClass(sourceFile) + ?: error("Class not found: $sourceFile. This error usually means that the class is not exposed to Objective-C.") + + fun getCallableDeclarationDescriptor(callableDeclaration: KirCallableDeclaration<*>): CallableMemberDescriptor = + kirToCallableDeclarationDescriptorCache[callableDeclaration] ?: error( + "Callable declaration not found: $callableDeclaration. " + + "Descriptors must be registered for all instantiated CallableDeclarations.", + ) + + fun getFunction(functionDescriptor: FunctionDescriptor): KirSimpleFunction = + findFunction(functionDescriptor) + ?: error("Function not found: $functionDescriptor. This error usually means that the function is not exposed to Objective-C.") + + fun getConstructor(constructorDescriptor: ClassConstructorDescriptor): KirConstructor = + findConstructor(constructorDescriptor) + ?: error("Constructor not found: $constructorDescriptor. This error usually means that the constructor is not exposed to Objective-C.") + + fun getValueParameter(valueParameterDescriptor: ParameterDescriptor): KirValueParameter = + findValueParameter(valueParameterDescriptor) + ?: error("Value parameter not found: $valueParameterDescriptor. Descriptors must be registered for all exported instantiated ParameterDescriptor.") + + fun getTypeParameterDescriptor(kirTypeParameter: KirTypeParameter): TypeParameterDescriptor = + typeParameterToDescriptorsCache[kirTypeParameter] ?: error( + "Type parameter not found: $kirTypeParameter. " + + "Descriptors must be registered for all instantiated TypeParameters.", + ) + + fun getClassDescriptor(kirClass: KirClass): ClassDescriptor = + findClassDescriptor(kirClass) + ?: error("Class descriptor not found: $kirClass. Descriptors must be registered for all exported instantiated KirClass.") + + fun getClassSourceFile(kirClass: KirClass): SourceFile = + findSourceFile(kirClass) + ?: error("Source file not found: $kirClass. Source files must be registered for all exported instantiated KirClass.") + + fun findClassDescriptor(kirClass: KirClass): ClassDescriptor? = + kirToClassDescriptorCache[kirClass] + + fun findSourceFile(kirClass: KirClass): SourceFile? = + kirToSourceFileCache[kirClass] + + fun findClass(classDescriptor: ClassDescriptor): KirClass? = + classDescriptorToKirCache[classDescriptor.original] + + fun findClass(sourceFile: SourceFile): KirClass? = + sourceFileToKirCache[sourceFile] + + fun findFunction(functionDescriptor: FunctionDescriptor): KirSimpleFunction? = + callableDeclarationDescriptorToKirCache[functionDescriptor] as? KirSimpleFunction + + fun findConstructor(constructorDescriptor: ClassConstructorDescriptor): KirConstructor? = + callableDeclarationDescriptorToKirCache[constructorDescriptor] as? KirConstructor + + fun findValueParameter(parameterDescriptor: ParameterDescriptor): KirValueParameter? = + kirToValueParameterDescriptorsCache[parameterDescriptor] + + fun findDeclarationDescriptor(kirElement: KirElement): DeclarationDescriptor? = + kirElementToDescriptorCache[kirElement] + + fun getExternalClass(descriptor: ClassDescriptor): KirClass = + getExternalClass(descriptor, addNSObjectSuperType = true) + + fun getExternalBuiltinClass(descriptor: ClassDescriptor): KirClass = + getExternalClass(descriptor, addNSObjectSuperType = false) + + private fun getExternalClass(descriptor: ClassDescriptor, addNSObjectSuperType: Boolean): KirClass = + externalClassesAndProtocolsCache.getOrPut(descriptor.original) { + val (name, kind) = if (descriptor.kind.isInterface) { + descriptor.name.asString().removeSuffix("Protocol") to KirClass.Kind.Interface + } else { + descriptor.name.asString() to KirClass.Kind.Class + } + + val kirClass = KirClass( + kotlinFqName = descriptor.fqNameSafe.asString(), + objCName = name, + swiftName = name, + parent = externalModule, + kind = kind, + origin = when { + descriptor.fqNameSafe.pathSegments()[0].asString() == "platform" -> KirClass.Origin.PlatformType + else -> KirClass.Origin.ExternalCinteropType + }, + superTypes = if (addNSObjectSuperType && kind != KirClass.Kind.Interface) { + listOf(kirBuiltins.NSObject.defaultType) + } else { + emptyList() + }, + isSealed = false, + hasUnexposedSealedSubclasses = false, + configuration = externalClassConfiguration, + ) + + registerClass(kirClass, descriptor) + + // Obj-C classes do not have type parameters in Kotlin + + kirClass + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirCallableDeclaration.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirCallableDeclaration.kt index d66aaf552..ba0c93667 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirCallableDeclaration.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirCallableDeclaration.kt @@ -3,14 +3,9 @@ package co.touchlab.skie.kir.element import co.touchlab.skie.configuration.CallableDeclarationConfiguration import co.touchlab.skie.oir.element.OirCallableDeclaration import co.touchlab.skie.sir.element.SirCallableDeclaration -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor sealed interface KirCallableDeclaration : KirElement, KirBridgeableDeclaration { - val baseDescriptor: CallableMemberDescriptor - - val descriptor: CallableMemberDescriptor - val owner: KirClass val origin: Origin @@ -25,6 +20,8 @@ sealed interface KirCallableDeclaration : KirElement val isRefinedInSwift: Boolean + val kotlinSignature: String + val module: KirModule get() = owner.module diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirClass.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirClass.kt index 8e724eea3..19ef40467 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirClass.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirClass.kt @@ -1,22 +1,22 @@ package co.touchlab.skie.kir.element import co.touchlab.skie.configuration.ClassConfiguration -import co.touchlab.skie.kir.type.ReferenceKirType +import co.touchlab.skie.kir.type.DeclarationBackedKirType +import co.touchlab.skie.kir.type.DeclaredKirType +import co.touchlab.skie.kir.type.KirType import co.touchlab.skie.oir.element.OirClass import co.touchlab.skie.sir.element.SirClass -import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.SourceFile class KirClass( - val descriptor: Descriptor, - val name: ObjCExportNamer.ClassOrProtocolName, + val kotlinFqName: String, + val objCName: String, + val swiftName: String, val parent: KirClassParent, val kind: Kind, - superTypes: List, + val origin: Origin, + superTypes: List, val isSealed: Boolean, val hasUnexposedSealedSubclasses: Boolean, - val belongsToSkieKotlinRuntime: Boolean, val configuration: ClassConfiguration, ) : KirClassParent, KirBridgeableDeclaration { @@ -24,6 +24,10 @@ class KirClass( override val classes: MutableList = mutableListOf() + val kotlinIdentifier: String by lazy { + kotlinFqName.substringAfterLast('.') + } + var companionObject: KirClass? = null val callableDeclarations: MutableList> = mutableListOf() @@ -32,7 +36,7 @@ class KirClass( val sealedSubclasses: MutableList = mutableListOf() - val superTypes: MutableList = superTypes.toMutableList() + val superTypes: MutableList = superTypes.toMutableList() val typeParameters: MutableList = mutableListOf() @@ -42,9 +46,11 @@ class KirClass( override val originalSirDeclaration: SirClass get() = oirClass.originalSirClass + // Should not be directly accessed before all bridging configuration is done. See @MustBeExecutedAfterBridgingConfiguration. override val primarySirDeclaration: SirClass get() = oirClass.primarySirClass + // Should not be directly accessed before all bridging configuration is done. See @MustBeExecutedAfterBridgingConfiguration. override var bridgedSirDeclaration: SirClass? get() = oirClass.bridgedSirClass set(value) { @@ -61,40 +67,38 @@ class KirClass( parent.classes.add(this) } - override fun toString(): String = "${this::class.simpleName}: $descriptorString" + val defaultType: DeclaredKirType by lazy { + toType(emptyList()) + } - private val descriptorString: String - get() = when (descriptor) { - is Descriptor.Class -> descriptor.value.toString() - is Descriptor.File -> descriptor.value.name ?: descriptor.value.toString() - } + fun toType(typeArguments: List): DeclaredKirType = + DeclaredKirType(this, typeArguments = typeArguments) + + fun toType(vararg typeArguments: KirType): DeclaredKirType = + toType(typeArguments.toList()) + + override fun toString(): String = "${this::class.simpleName}: $kotlinFqName" enum class Kind { Class, Interface, File, Enum, Object, CompanionObject } - sealed interface Descriptor { + sealed interface Origin { - data class Class(val value: ClassDescriptor) : Descriptor + object Kotlin : Origin - data class File(val value: SourceFile) : Descriptor - } -} + object PlatformType : Origin -val KirClass.classDescriptorOrNull: ClassDescriptor? - get() = when (val descriptor = descriptor) { - is KirClass.Descriptor.Class -> descriptor.value - is KirClass.Descriptor.File -> null + object ExternalCinteropType : Origin } +} -val KirClass.classDescriptorOrError: ClassDescriptor - get() = classDescriptorOrNull ?: error("Class descriptor is not available for file classes. Was: $this") +val KirClass.superClassType: DeclaredKirType? + get() = superTypes.firstOrNull { + val declaredType = it as? DeclaredKirType ?: return@firstOrNull false -val KirClass.sourceFileOrNull: SourceFile? - get() = when (val descriptor = descriptor) { - is KirClass.Descriptor.Class -> null - is KirClass.Descriptor.File -> descriptor.value - } + declaredType.declaration.kind != KirClass.Kind.Interface + } as DeclaredKirType? -val KirClass.sourceFileOrError: SourceFile - get() = sourceFileOrNull ?: error("Source file is not available for real classes. Was: $this") +val KirClass.superClass: KirClass? + get() = superClassType?.declaration diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirConstructor.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirConstructor.kt index d91e20932..121f3102f 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirConstructor.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirConstructor.kt @@ -4,19 +4,18 @@ import co.touchlab.skie.configuration.ConstructorConfiguration import co.touchlab.skie.oir.element.OirConstructor import co.touchlab.skie.oir.element.OirFunction import co.touchlab.skie.sir.element.SirConstructor -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor class KirConstructor( - override val descriptor: ConstructorDescriptor, + override val kotlinName: String, + override val kotlinSignature: String, + override val objCSelector: String, + override val swiftName: String, override val owner: KirClass, override val errorHandlingStrategy: OirFunction.ErrorHandlingStrategy, override val deprecationLevel: DeprecationLevel, override val configuration: ConstructorConfiguration, ) : KirFunction() { - override val baseDescriptor: ConstructorDescriptor - get() = descriptor - override val scope: KirScope = KirScope.Static override val isRefinedInSwift: Boolean = false @@ -59,6 +58,4 @@ class KirConstructor( init { owner.callableDeclarations.add(this) } - - override fun toString(): String = "${this::class.simpleName}: $descriptor" } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirEnumEntry.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirEnumEntry.kt index 0845cd601..545e9e97b 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirEnumEntry.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirEnumEntry.kt @@ -2,12 +2,14 @@ package co.touchlab.skie.kir.element import co.touchlab.skie.oir.element.OirProperty import co.touchlab.skie.sir.element.SirProperty -import org.jetbrains.kotlin.descriptors.ClassDescriptor class KirEnumEntry( - val descriptor: ClassDescriptor, + val kotlinName: String, + val objCSelector: String, + val swiftName: String, val owner: KirClass, val index: Int, + val hasUserDefinedName: Boolean, ) : KirElement { lateinit var oirEnumEntry: OirProperty @@ -19,5 +21,5 @@ class KirEnumEntry( owner.enumEntries.add(this) } - override fun toString(): String = "${this::class.simpleName}: $descriptor" + override fun toString(): String = "${this::class.simpleName}: $kotlinName" } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirFunction.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirFunction.kt index 7ce5e0741..e2b14dc8b 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirFunction.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirFunction.kt @@ -3,16 +3,16 @@ package co.touchlab.skie.kir.element import co.touchlab.skie.configuration.FunctionConfiguration import co.touchlab.skie.oir.element.OirFunction import co.touchlab.skie.sir.element.SirFunction -import org.jetbrains.kotlin.descriptors.FunctionDescriptor sealed class KirFunction : KirCallableDeclaration { - val name: String - get() = descriptor.name.asString() + abstract val kotlinName: String - abstract val errorHandlingStrategy: OirFunction.ErrorHandlingStrategy + abstract val objCSelector: String + + abstract val swiftName: String - abstract override val baseDescriptor: FunctionDescriptor + abstract val errorHandlingStrategy: OirFunction.ErrorHandlingStrategy abstract val valueParameters: MutableList @@ -20,5 +20,5 @@ sealed class KirFunction : KirCallableDeclaration { abstract override val configuration: FunctionConfiguration - override fun toString(): String = "${this::class.simpleName}: $descriptor" + override fun toString(): String = "${this::class.simpleName}: $kotlinName ($owner)" } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirModule.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirModule.kt index 1a9b2a70d..fab3e835a 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirModule.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirModule.kt @@ -1,15 +1,13 @@ package co.touchlab.skie.kir.element import co.touchlab.skie.configuration.ModuleConfiguration -import org.jetbrains.kotlin.descriptors.ModuleDescriptor // Instantiate only in KirProvider class KirModule( val name: String, val project: KirProject, - val descriptor: ModuleDescriptor?, - val isSkieKotlinRuntime: Boolean, val configuration: ModuleConfiguration, + val origin: Origin, ) : KirClassParent { override val classes: MutableList = mutableListOf() @@ -22,4 +20,8 @@ class KirModule( } override fun toString(): String = "${this::class.simpleName}: $name" + + enum class Origin { + Kotlin, SkieRuntime, SkieGenerated, External + } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirProperty.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirProperty.kt index aa2a748da..031f50c68 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirProperty.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirProperty.kt @@ -5,11 +5,12 @@ import co.touchlab.skie.kir.type.KirType import co.touchlab.skie.oir.element.OirCallableDeclaration import co.touchlab.skie.oir.element.OirProperty import co.touchlab.skie.sir.element.SirProperty -import org.jetbrains.kotlin.descriptors.PropertyDescriptor class KirProperty( - override val baseDescriptor: PropertyDescriptor, - override val descriptor: PropertyDescriptor, + val kotlinName: String, + override val kotlinSignature: String, + val objCName: String, + val swiftName: String, override val owner: KirClass, override val origin: KirCallableDeclaration.Origin, override val scope: KirScope, @@ -20,9 +21,6 @@ class KirProperty( override val configuration: PropertyConfiguration, ) : KirOverridableDeclaration { - val name: String - get() = descriptor.name.asString() - lateinit var oirProperty: OirProperty override val oirCallableDeclaration: OirCallableDeclaration @@ -78,5 +76,5 @@ class KirProperty( overridableDeclarationDelegate.removeOverriddenBy(declaration) } - override fun toString(): String = "${this::class.simpleName}: $descriptor" + override fun toString(): String = "${this::class.simpleName}: $kotlinName" } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirSimpleFunction.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirSimpleFunction.kt index f924c48ad..714ba7668 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirSimpleFunction.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirSimpleFunction.kt @@ -6,12 +6,12 @@ import co.touchlab.skie.oir.element.OirCallableDeclaration import co.touchlab.skie.oir.element.OirFunction import co.touchlab.skie.oir.element.OirSimpleFunction import co.touchlab.skie.sir.element.SirSimpleFunction -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor class KirSimpleFunction( - override val baseDescriptor: FunctionDescriptor, - override val descriptor: FunctionDescriptor, + override val kotlinName: String, + override val kotlinSignature: String, + override val objCSelector: String, + override val swiftName: String, override val owner: KirClass, override val origin: KirCallableDeclaration.Origin, val isSuspend: Boolean, @@ -83,14 +83,12 @@ class KirSimpleFunction( overridableDeclarationDelegate.removeOverriddenBy(declaration) } - override fun toString(): String = "${this::class.simpleName}: $descriptor" - sealed interface Kind { object Function : Kind - data class PropertyGetter(val propertyDescriptor: PropertyDescriptor) : Kind + data class PropertyGetter(var associatedSetter: KirSimpleFunction?) : Kind - data class PropertySetter(val propertyDescriptor: PropertyDescriptor) : Kind + data class PropertySetter(var associatedGetter: KirSimpleFunction?) : Kind } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirTypeParameter.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirTypeParameter.kt index 48bc62cff..5d9fb8f69 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirTypeParameter.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirTypeParameter.kt @@ -1,11 +1,12 @@ package co.touchlab.skie.kir.element +import co.touchlab.skie.kir.type.TypeParameterUsageKirType import co.touchlab.skie.oir.element.OirTypeParameter -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor class KirTypeParameter( - val descriptor: TypeParameterDescriptor, + val name: String, val parent: KirClass, + val variance: OirTypeParameter.Variance, ) : KirElement { lateinit var oirTypeParameter: OirTypeParameter @@ -14,5 +15,8 @@ class KirTypeParameter( parent.typeParameters.add(this) } - override fun toString(): String = "${this::class.simpleName}: $descriptor>" + override fun toString(): String = "${this::class.simpleName}: $name" } + +fun KirTypeParameter.toTypeParameterUsage(): TypeParameterUsageKirType = + TypeParameterUsageKirType(this) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirValueParameter.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirValueParameter.kt index e4289283e..d07250221 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirValueParameter.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/element/KirValueParameter.kt @@ -4,13 +4,15 @@ import co.touchlab.skie.configuration.ValueParameterConfiguration import co.touchlab.skie.kir.type.KirType import co.touchlab.skie.oir.element.OirValueParameter import co.touchlab.skie.sir.element.SirValueParameter -import org.jetbrains.kotlin.descriptors.ParameterDescriptor class KirValueParameter( + val kotlinName: String, + val objCName: String, val parent: KirFunction<*>, var type: KirType, val kind: Kind, val configuration: ValueParameterConfiguration, + val wasTypeInlined: Boolean, ) : KirElement { lateinit var oirValueParameter: OirValueParameter @@ -18,37 +20,15 @@ class KirValueParameter( val originalSirValueParameter: SirValueParameter? get() = oirValueParameter.originalSirValueParameter - val descriptorOrNull: ParameterDescriptor? - get() = when (kind) { - is Kind.ValueParameter -> kind.descriptor - else -> null - } - - val name: String - get() = when (kind) { - is Kind.ValueParameter -> kind.descriptor.name.asString() - Kind.Receiver -> "receiver" - Kind.PropertySetterValue -> "value" - Kind.ErrorOut -> "error" - Kind.SuspendCompletion -> "completionHandler" - } - init { parent.valueParameters.add(this) } - override fun toString(): String = "${this::class.simpleName}: $name: $type" + override fun toString(): String = "${this::class.simpleName}: $kotlinName: $type" sealed interface Kind { - val descriptorOrNull: ParameterDescriptor? - get() = null - - data class ValueParameter(val descriptor: ParameterDescriptor) : Kind { - - override val descriptorOrNull: ParameterDescriptor - get() = descriptor - } + object ValueParameter : Kind object Receiver : Kind diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/BlockPointerKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/BlockPointerKirType.kt index c7836abd0..07794941a 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/BlockPointerKirType.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/BlockPointerKirType.kt @@ -1,5 +1,6 @@ package co.touchlab.skie.kir.type -import org.jetbrains.kotlin.types.KotlinType - -data class BlockPointerKirType(val kotlinType: KotlinType, val returnsVoid: Boolean) : KirType() +data class BlockPointerKirType( + val valueParameterTypes: List, + val returnType: KirType, +) : NonNullReferenceKirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/DeclarationBackedKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/DeclarationBackedKirType.kt new file mode 100644 index 000000000..2b82dde27 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/DeclarationBackedKirType.kt @@ -0,0 +1,3 @@ +package co.touchlab.skie.kir.type + +sealed class DeclarationBackedKirType : NonNullReferenceKirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/DeclaredKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/DeclaredKirType.kt new file mode 100644 index 000000000..50a64a483 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/DeclaredKirType.kt @@ -0,0 +1,8 @@ +package co.touchlab.skie.kir.type + +import co.touchlab.skie.kir.element.KirClass + +data class DeclaredKirType( + val declaration: KirClass, + val typeArguments: List, +) : DeclarationBackedKirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/ErrorOutKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/ErrorOutKirType.kt deleted file mode 100644 index 9e69bab8a..000000000 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/ErrorOutKirType.kt +++ /dev/null @@ -1,3 +0,0 @@ -package co.touchlab.skie.kir.type - -object ErrorOutKirType : KirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/NonNullReferenceKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/NonNullReferenceKirType.kt new file mode 100644 index 000000000..46a459962 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/NonNullReferenceKirType.kt @@ -0,0 +1,3 @@ +package co.touchlab.skie.kir.type + +sealed class NonNullReferenceKirType : ReferenceKirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/NullableReferenceKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/NullableReferenceKirType.kt new file mode 100644 index 000000000..c7c5f475a --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/NullableReferenceKirType.kt @@ -0,0 +1,6 @@ +package co.touchlab.skie.kir.type + +data class NullableReferenceKirType( + val nonNullType: NonNullReferenceKirType, + val isNullableResult: Boolean = false, +) : ReferenceKirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/PointerKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/PointerKirType.kt new file mode 100644 index 000000000..2490e203f --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/PointerKirType.kt @@ -0,0 +1,6 @@ +package co.touchlab.skie.kir.type + +data class PointerKirType( + val pointee: KirType, + val nullable: Boolean, +) : KirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/ReferenceKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/ReferenceKirType.kt index 6589a1536..7b926f489 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/ReferenceKirType.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/ReferenceKirType.kt @@ -1,5 +1,3 @@ package co.touchlab.skie.kir.type -import org.jetbrains.kotlin.types.KotlinType - -data class ReferenceKirType(val kotlinType: KotlinType) : KirType() +sealed class ReferenceKirType : KirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/SpecialOirKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/SpecialOirKirType.kt new file mode 100644 index 000000000..d6a3b3663 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/SpecialOirKirType.kt @@ -0,0 +1,5 @@ +package co.touchlab.skie.kir.type + +import co.touchlab.skie.oir.type.SpecialReferenceOirType + +data class SpecialOirKirType(val oirType: SpecialReferenceOirType) : NonNullReferenceKirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/SuspendCompletionKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/SuspendCompletionKirType.kt deleted file mode 100644 index 0833e067c..000000000 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/SuspendCompletionKirType.kt +++ /dev/null @@ -1,5 +0,0 @@ -package co.touchlab.skie.kir.type - -import org.jetbrains.kotlin.types.KotlinType - -data class SuspendCompletionKirType(val kotlinType: KotlinType, val useUnitCompletion: Boolean) : KirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/TypeParameterUsageKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/TypeParameterUsageKirType.kt new file mode 100644 index 000000000..de9691822 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/TypeParameterUsageKirType.kt @@ -0,0 +1,7 @@ +package co.touchlab.skie.kir.type + +import co.touchlab.skie.kir.element.KirTypeParameter + +data class TypeParameterUsageKirType( + val typeParameter: KirTypeParameter, +) : NonNullReferenceKirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/UnresolvedFlowKirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/UnresolvedFlowKirType.kt new file mode 100644 index 000000000..3f2bfb718 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/UnresolvedFlowKirType.kt @@ -0,0 +1,9 @@ +package co.touchlab.skie.kir.type + +import co.touchlab.skie.kir.type.translation.KirTypeTranslator +import co.touchlab.skie.phases.features.flow.SupportedFlow + +data class UnresolvedFlowKirType( + val flowType: SupportedFlow.Variant, + val evaluateFlowTypeArgument: KirTypeTranslator.() -> NonNullReferenceKirType, +) : DeclarationBackedKirType() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirCustomTypeMapper.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirCustomTypeMapper.kt new file mode 100644 index 000000000..af982c6ee --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirCustomTypeMapper.kt @@ -0,0 +1,15 @@ +package co.touchlab.skie.kir.type.translation + +import co.touchlab.skie.kir.type.NonNullReferenceKirType +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.types.KotlinType + +interface KirCustomTypeMapper { + + val mappedClassId: ClassId + + context(KirTypeParameterScope) + fun mapType( + mappedSuperType: KotlinType, + ): NonNullReferenceKirType +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirCustomTypeMappers.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirCustomTypeMappers.kt similarity index 56% rename from SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirCustomTypeMappers.kt rename to SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirCustomTypeMappers.kt index a3df2001e..a46cb4d6f 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirCustomTypeMappers.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirCustomTypeMappers.kt @@ -1,11 +1,11 @@ @file:Suppress("invisible_reference", "invisible_member") -package co.touchlab.skie.oir.type.translation +package co.touchlab.skie.kir.type.translation import co.touchlab.skie.kir.builtin.KirBuiltins -import co.touchlab.skie.oir.builtin.OirBuiltins -import co.touchlab.skie.oir.element.OirClass -import co.touchlab.skie.oir.type.NonNullReferenceOirType +import co.touchlab.skie.kir.element.KirClass +import co.touchlab.skie.kir.type.NonNullReferenceKirType +import co.touchlab.skie.kir.type.SpecialOirKirType import co.touchlab.skie.oir.type.SpecialReferenceOirType import org.jetbrains.kotlin.backend.konan.objcexport.isMappedFunctionClass import org.jetbrains.kotlin.builtins.StandardNames @@ -13,13 +13,14 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.typeUtil.supertypes -class OirCustomTypeMappers( +class KirCustomTypeMappers( private val kirBuiltins: KirBuiltins, - private val oirBuiltins: OirBuiltins, - translator: Lazy, + translator: Lazy, ) { private val translator by translator @@ -29,28 +30,50 @@ class OirCustomTypeMappers( * * Don't forget to update [hiddenTypes] after adding new one. */ - private val predefined: Map by lazy { + private val predefined: Map by lazy { with(StandardNames.FqNames) { - val result = mutableListOf() + val result = mutableListOf() - result += Collection(list, oirBuiltins.NSArray) - result += Collection(mutableList, oirBuiltins.NSMutableArray) - result += Collection(set, oirBuiltins.NSSet) - result += Collection(mutableSet, kirBuiltins.MutableSet.oirClass) - result += Collection(map, oirBuiltins.NSDictionary) - result += Collection(mutableMap, kirBuiltins.MutableMap.oirClass) + result += Collection(list, kirBuiltins.NSArray) + result += Collection(mutableList, kirBuiltins.NSMutableArray) + result += Collection(set, kirBuiltins.NSSet) + result += Collection(mutableSet, kirBuiltins.MutableSet) + result += Collection(map, kirBuiltins.NSDictionary) + result += Collection(mutableMap, kirBuiltins.MutableMap) kirBuiltins.nsNumberDeclarations.forEach { (classId, kirClass) -> - result += Simple(classId, kirClass.oirClass) + result += Simple(classId, kirClass) } - result += Simple(ClassId.topLevel(string.toSafe()), oirBuiltins.NSString) + result += Simple(ClassId.topLevel(string.toSafe()), kirBuiltins.NSString) result.associateBy { it.mappedClassId } } } - fun getMapper(descriptor: ClassDescriptor): OirCustomTypeMapper? { + context(KirTypeParameterScope) + fun mapTypeIfApplicable(kotlinType: KotlinType): NonNullReferenceKirType? { + val typeMappingMatches = (listOf(kotlinType) + kotlinType.supertypes()).mapNotNull { type -> + (type.constructor.declarationDescriptor as? ClassDescriptor)?.let { descriptor -> + getMapper(descriptor)?.let { mapper -> + TypeMappingMatch(type, descriptor, mapper) + } + } + } + + val mostSpecificMatches = typeMappingMatches.filter { match -> + typeMappingMatches.all { otherMatch -> + otherMatch.descriptor == match.descriptor || + !otherMatch.descriptor.isSubclassOf(match.descriptor) + } + } + + return mostSpecificMatches.firstOrNull()?.let { + withTypeParameterScopeFor(it.type) { it.mapper.mapType(it.type) } ?: SpecialOirKirType(SpecialReferenceOirType.Id) + } + } + + private fun getMapper(descriptor: ClassDescriptor): KirCustomTypeMapper? { val classId = descriptor.classId predefined[classId]?.let { return it } @@ -83,49 +106,52 @@ class OirCustomTypeMappers( "kotlin.collections.MutableIterable", ).map { ClassId.topLevel(FqName(it)) }.toSet() + private class TypeMappingMatch(val type: KotlinType, val descriptor: ClassDescriptor, val mapper: KirCustomTypeMapper) + private inner class Simple( override val mappedClassId: ClassId, - private val oirClass: OirClass, - ) : OirCustomTypeMapper { + private val kirClass: KirClass, + ) : KirCustomTypeMapper { - override fun mapType(mappedSuperType: KotlinType, oirTypeParameterScope: OirTypeParameterScope): NonNullReferenceOirType = - oirClass.defaultType + context(KirTypeParameterScope) + override fun mapType(mappedSuperType: KotlinType): NonNullReferenceKirType = + kirClass.defaultType } private inner class Collection( mappedClassFqName: FqName, - private val oirClass: OirClass, - ) : OirCustomTypeMapper { + private val kirClass: KirClass, + ) : KirCustomTypeMapper { override val mappedClassId = ClassId.topLevel(mappedClassFqName) + context(KirTypeParameterScope) override fun mapType( mappedSuperType: KotlinType, - oirTypeParameterScope: OirTypeParameterScope, - ): NonNullReferenceOirType { + ): NonNullReferenceKirType { val typeArguments = mappedSuperType.arguments.map { val argument = it.type if (TypeUtils.isNullableType(argument)) { // Kotlin `null` keys and values are represented as `NSNull` singleton. - SpecialReferenceOirType.Id + SpecialOirKirType(SpecialReferenceOirType.Id) } else { - translator.mapReferenceTypeIgnoringNullability(argument, oirTypeParameterScope) + translator.mapReferenceTypeIgnoringNullability(argument) } } - return oirClass.toType(typeArguments) + return kirClass.toType(typeArguments) } } - private inner class Function(private val parameterCount: Int) : OirCustomTypeMapper { + private inner class Function(private val parameterCount: Int) : KirCustomTypeMapper { override val mappedClassId: ClassId get() = StandardNames.getFunctionClassId(parameterCount) + context(KirTypeParameterScope) override fun mapType( mappedSuperType: KotlinType, - oirTypeParameterScope: OirTypeParameterScope, - ): NonNullReferenceOirType = - translator.mapFunctionTypeIgnoringNullability(mappedSuperType, oirTypeParameterScope, returnsVoid = false) + ): NonNullReferenceKirType = + translator.mapFunctionTypeIgnoringNullability(mappedSuperType, returnsVoid = false) } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirDeclarationTypeTranslator.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirDeclarationTypeTranslator.kt new file mode 100644 index 000000000..26164b41c --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirDeclarationTypeTranslator.kt @@ -0,0 +1,158 @@ +@file:Suppress("invisible_reference", "invisible_member") + +package co.touchlab.skie.kir.type.translation + +import co.touchlab.skie.kir.builtin.KirBuiltins +import co.touchlab.skie.kir.type.BlockPointerKirType +import co.touchlab.skie.kir.type.KirType +import co.touchlab.skie.kir.type.NonNullReferenceKirType +import co.touchlab.skie.kir.type.NullableReferenceKirType +import co.touchlab.skie.kir.type.OirBasedKirType +import co.touchlab.skie.kir.type.PointerKirType +import co.touchlab.skie.oir.type.PointerOirType +import co.touchlab.skie.oir.type.PrimitiveOirType +import co.touchlab.skie.oir.type.SpecialReferenceOirType +import co.touchlab.skie.oir.type.VoidOirType +import org.jetbrains.kotlin.backend.konan.binaryRepresentationIsNullable +import org.jetbrains.kotlin.backend.konan.objcexport.BlockPointerBridge +import org.jetbrains.kotlin.backend.konan.objcexport.MethodBridge +import org.jetbrains.kotlin.backend.konan.objcexport.MethodBridgeValueParameter +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCValueType +import org.jetbrains.kotlin.backend.konan.objcexport.ReferenceBridge +import org.jetbrains.kotlin.backend.konan.objcexport.TypeBridge +import org.jetbrains.kotlin.backend.konan.objcexport.ValueTypeBridge +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ParameterDescriptor +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.typeUtil.builtIns +import org.jetbrains.kotlin.types.typeUtil.supertypes + +class KirDeclarationTypeTranslator( + private val kirTypeTranslator: KirTypeTranslator, + kirBuiltins: KirBuiltins, +) : KirTypeTranslatorUtilityScope() { + + private val nullableNSErrorType = kirBuiltins.NSError.defaultType.withNullabilityOf(true) + + context(KirTypeParameterScope) + internal fun mapValueParameterType( + functionDescriptor: FunctionDescriptor, + valueParameterDescriptor: ParameterDescriptor?, + bridge: MethodBridgeValueParameter, + ): KirType = + when (bridge) { + is MethodBridgeValueParameter.Mapped -> mapType(valueParameterDescriptor!!.type, bridge.bridge) + MethodBridgeValueParameter.ErrorOutParameter -> { + PointerKirType(nullableNSErrorType, nullable = true) + } + is MethodBridgeValueParameter.SuspendCompletion -> { + mapSuspendCompletionType(functionDescriptor.returnType!!, useUnitCompletion = bridge.useUnitCompletion) + } + } + + context(KirTypeParameterScope) + internal fun mapReturnType( + descriptor: FunctionDescriptor, + returnBridge: MethodBridge.ReturnValue, + ): KirType = + when (returnBridge) { + MethodBridge.ReturnValue.Suspend, + MethodBridge.ReturnValue.Void, + -> VoidOirType.toKirType() + MethodBridge.ReturnValue.HashCode -> PrimitiveOirType.NSUInteger.toKirType() + is MethodBridge.ReturnValue.Mapped -> mapType(descriptor.returnType!!, returnBridge.bridge) + MethodBridge.ReturnValue.WithError.Success -> PrimitiveOirType.BOOL.toKirType() + is MethodBridge.ReturnValue.WithError.ZeroForError -> { + val successReturnType = mapReturnType(descriptor, returnBridge.successBridge) + + successReturnType.makeNullableIfReferenceOrPointer() + } + + MethodBridge.ReturnValue.Instance.InitResult, + MethodBridge.ReturnValue.Instance.FactoryResult, + -> SpecialReferenceOirType.InstanceType.toKirType() + } + + context(KirTypeParameterScope) + private fun mapType(kotlinType: KotlinType, typeBridge: TypeBridge): KirType = + when (typeBridge) { + ReferenceBridge -> kirTypeTranslator.mapReferenceType(kotlinType) + is BlockPointerBridge -> mapFunctionType(kotlinType, typeBridge) + is ValueTypeBridge -> mapValueType(kotlinType, typeBridge) + } + + context(KirTypeParameterScope) + private fun mapSuspendCompletionType(kotlinType: KotlinType, useUnitCompletion: Boolean): BlockPointerKirType { + val resultType = if (useUnitCompletion) { + null + } else { + when (val it = kirTypeTranslator.mapReferenceType(kotlinType)) { + is NonNullReferenceKirType -> NullableReferenceKirType(it, isNullableResult = false) + is NullableReferenceKirType -> NullableReferenceKirType(it.nonNullType, isNullableResult = true) + } + } + + return BlockPointerKirType( + valueParameterTypes = listOfNotNull( + resultType, + nullableNSErrorType, + ), + returnType = VoidOirType.toKirType(), + ) + } + + context(KirTypeParameterScope) + private fun mapFunctionType( + kotlinType: KotlinType, + typeBridge: BlockPointerBridge, + ): KirType { + val expectedDescriptor = kotlinType.builtIns.getFunction(typeBridge.numberOfParameters) + + // Somewhat similar to mapType: + val functionType = if (TypeUtils.getClassDescriptor(kotlinType) == expectedDescriptor) { + kotlinType + } else { + kotlinType.supertypes().singleOrNull { TypeUtils.getClassDescriptor(it) == expectedDescriptor } + ?: expectedDescriptor.defaultType // Should not happen though. + } + + return kirTypeTranslator.mapFunctionType(functionType, typeBridge.returnsVoid) + } + + private fun mapValueType( + kotlinType: KotlinType, + typeBridge: ValueTypeBridge, + ): KirType = + when (typeBridge.objCValueType) { + ObjCValueType.BOOL -> PrimitiveOirType.BOOL + ObjCValueType.UNICHAR -> PrimitiveOirType.unichar + ObjCValueType.CHAR -> PrimitiveOirType.int8_t + ObjCValueType.SHORT -> PrimitiveOirType.int16_t + ObjCValueType.INT -> PrimitiveOirType.int32_t + ObjCValueType.LONG_LONG -> PrimitiveOirType.int64_t + ObjCValueType.UNSIGNED_CHAR -> PrimitiveOirType.uint8_t + ObjCValueType.UNSIGNED_SHORT -> PrimitiveOirType.uint16_t + ObjCValueType.UNSIGNED_INT -> PrimitiveOirType.uint32_t + ObjCValueType.UNSIGNED_LONG_LONG -> PrimitiveOirType.uint64_t + ObjCValueType.FLOAT -> PrimitiveOirType.float + ObjCValueType.DOUBLE -> PrimitiveOirType.double + ObjCValueType.POINTER -> PointerOirType(VoidOirType, kotlinType.binaryRepresentationIsNullable()) + }.toKirType() + + private fun KirType.makeNullableIfReferenceOrPointer(): KirType = + when (this) { + is NullableReferenceKirType -> this + is NonNullReferenceKirType -> NullableReferenceKirType(this) + is PointerKirType -> this.copy(nullable = true) + is OirBasedKirType -> this.makeNullableIfReferenceOrPointer() + } + + private fun OirBasedKirType.makeNullableIfReferenceOrPointer(): KirType = + when (this.oirType) { + is PointerOirType -> this.oirType.copy(nullable = true).toKirType() + is PrimitiveOirType -> this + VoidOirType -> this + else -> error("Unsupported OirBasedKirType type: $this") + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeParameterScope.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeParameterScope.kt new file mode 100644 index 000000000..2e26ab5ba --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeParameterScope.kt @@ -0,0 +1,85 @@ +package co.touchlab.skie.kir.type.translation + +import co.touchlab.skie.kir.descriptor.DescriptorKirProvider +import co.touchlab.skie.kir.element.KirClass +import co.touchlab.skie.kir.element.KirTypeParameter +import co.touchlab.skie.kir.element.toTypeParameterUsage +import co.touchlab.skie.kir.type.TypeParameterUsageKirType +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.types.KotlinType +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract + +interface KirTypeParameterScope { + + val parent: KirTypeParameterScope? + + context(DescriptorKirProvider) + fun getTypeParameterUsage(typeParameterDescriptor: TypeParameterDescriptor?): TypeParameterUsageKirType? = + parent?.getTypeParameterUsage(typeParameterDescriptor) + + fun wasTypeAlreadyVisited(type: KotlinType): Boolean = + parent?.wasTypeAlreadyVisited(type) ?: false +} + +inline fun KirTypeParameterScope.withTypeParameterScopeFor(type: KotlinType, action: KirTypeParameterScope.() -> T): T? = + KirTypeParameterTypeScope(this, type)?.let(action) + +@OptIn(ExperimentalContracts::class) +inline fun KirClass.withTypeParameterScope(action: KirTypeParameterScope.() -> Unit) { + contract { + callsInPlace(action, kotlin.contracts.InvocationKind.EXACTLY_ONCE) + } + + val scope = when (kind) { + KirClass.Kind.Class -> KirTypeParameterClassScope(KirTypeParameterRootScope, typeParameters) + else -> KirTypeParameterRootScope + } + + scope.action() +} + +object KirTypeParameterRootScope : KirTypeParameterScope { + + override val parent: KirTypeParameterScope? = null +} + +class KirTypeParameterClassScope( + override val parent: KirTypeParameterScope, + private val typeParameters: List, +) : KirTypeParameterScope { + + context(DescriptorKirProvider) + override fun getTypeParameterUsage(typeParameterDescriptor: TypeParameterDescriptor?): TypeParameterUsageKirType? { + if (typeParameterDescriptor == null) { + return null + } + + return typeParameters + .firstOrNull { + val descriptor = getTypeParameterDescriptor(it) + + descriptor == typeParameterDescriptor || (descriptor.isCapturedFromOuterDeclaration && descriptor.original == typeParameterDescriptor) + } + ?.toTypeParameterUsage() + } +} + +class KirTypeParameterTypeScope private constructor( + override val parent: KirTypeParameterScope, + private val type: KotlinType, +) : KirTypeParameterScope { + + override fun wasTypeAlreadyVisited(type: KotlinType): Boolean = + type == this.type || super.wasTypeAlreadyVisited(type) + + companion object { + + operator fun invoke(parent: KirTypeParameterScope, type: KotlinType): KirTypeParameterTypeScope? = + if (parent.wasTypeAlreadyVisited(type)) { + null + } else { + KirTypeParameterTypeScope(parent, type) + } + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeTranslator.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeTranslator.kt index 825451ffb..e2e13d93a 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeTranslator.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeTranslator.kt @@ -1,132 +1,154 @@ -@file:Suppress("invisible_reference", "invisible_member") - package co.touchlab.skie.kir.type.translation +import co.touchlab.skie.kir.descriptor.DescriptorKirProvider +import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.kir.type.BlockPointerKirType -import co.touchlab.skie.kir.type.ErrorOutKirType -import co.touchlab.skie.kir.type.KirType -import co.touchlab.skie.kir.type.OirBasedKirType +import co.touchlab.skie.kir.type.NonNullReferenceKirType import co.touchlab.skie.kir.type.ReferenceKirType -import co.touchlab.skie.kir.type.SuspendCompletionKirType -import co.touchlab.skie.oir.type.OirType -import co.touchlab.skie.oir.type.PointerOirType -import co.touchlab.skie.oir.type.PrimitiveOirType +import co.touchlab.skie.kir.type.UnresolvedFlowKirType import co.touchlab.skie.oir.type.SpecialReferenceOirType import co.touchlab.skie.oir.type.VoidOirType -import org.jetbrains.kotlin.backend.konan.binaryRepresentationIsNullable -import org.jetbrains.kotlin.backend.konan.objcexport.BlockPointerBridge -import org.jetbrains.kotlin.backend.konan.objcexport.MethodBridge -import org.jetbrains.kotlin.backend.konan.objcexport.MethodBridgeValueParameter -import org.jetbrains.kotlin.backend.konan.objcexport.ObjCValueType -import org.jetbrains.kotlin.backend.konan.objcexport.ReferenceBridge -import org.jetbrains.kotlin.backend.konan.objcexport.TypeBridge -import org.jetbrains.kotlin.backend.konan.objcexport.ValueTypeBridge -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.ParameterDescriptor +import co.touchlab.skie.phases.features.flow.SupportedFlow +import org.jetbrains.kotlin.backend.konan.isExternalObjCClass +import org.jetbrains.kotlin.backend.konan.isInlined +import org.jetbrains.kotlin.backend.konan.isKotlinObjCClass +import org.jetbrains.kotlin.backend.konan.isObjCForwardDeclaration +import org.jetbrains.kotlin.backend.konan.isObjCMetaClass +import org.jetbrains.kotlin.backend.konan.isObjCObjectType +import org.jetbrains.kotlin.backend.konan.isObjCProtocolClass +import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isAny +import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType +import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType +import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeProjection import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.typeUtil.builtIns -import org.jetbrains.kotlin.types.typeUtil.makeNullable -import org.jetbrains.kotlin.types.typeUtil.supertypes - -class KirTypeTranslator { - - internal fun mapValueParameterType( - functionDescriptor: FunctionDescriptor, - valueParameterDescriptor: ParameterDescriptor?, - bridge: MethodBridgeValueParameter, - ): KirType = - when (bridge) { - is MethodBridgeValueParameter.Mapped -> mapType(valueParameterDescriptor!!.type, bridge.bridge) - MethodBridgeValueParameter.ErrorOutParameter -> ErrorOutKirType - is MethodBridgeValueParameter.SuspendCompletion -> { - SuspendCompletionKirType(functionDescriptor.returnType!!, useUnitCompletion = bridge.useUnitCompletion) - } +import org.jetbrains.kotlin.types.isNullable +import org.jetbrains.kotlin.types.typeUtil.isTypeParameter + +// Logic mostly copied from ObjCExportTranslatorImpl (including TODOs) +class KirTypeTranslator( + private val descriptorKirProvider: DescriptorKirProvider, + private val customTypeMappers: KirCustomTypeMappers, +) : KirTypeTranslatorUtilityScope() { + + context(KirTypeParameterScope) + fun mapReferenceType(kotlinType: KotlinType): ReferenceKirType = + mapReferenceTypeIgnoringNullability(kotlinType).withNullabilityOf(kotlinType) + + context(KirTypeParameterScope) + fun mapReferenceTypeIgnoringNullability(kotlinType: KotlinType): NonNullReferenceKirType { + mapTypeIfFlow(kotlinType)?.let { + return it + } + + customTypeMappers.mapTypeIfApplicable(kotlinType)?.let { + return it } - internal fun mapReturnType( - descriptor: FunctionDescriptor, - returnBridge: MethodBridge.ReturnValue, - ): KirType = - when (returnBridge) { - MethodBridge.ReturnValue.Suspend, - MethodBridge.ReturnValue.Void, - -> VoidOirType.toKirType() - MethodBridge.ReturnValue.HashCode -> PrimitiveOirType.NSUInteger.toKirType() - is MethodBridge.ReturnValue.Mapped -> mapType(descriptor.returnType!!, returnBridge.bridge) - MethodBridge.ReturnValue.WithError.Success -> PrimitiveOirType.BOOL.toKirType() - is MethodBridge.ReturnValue.WithError.ZeroForError -> { - val successReturnType = mapReturnType(descriptor, returnBridge.successBridge) - - successReturnType.makeNullableIfReferenceOrPointer() + if (kotlinType.isTypeParameter()) { + val genericTypeUsage = with(descriptorKirProvider) { + getTypeParameterUsage(TypeUtils.getTypeParameterDescriptorOrNull(kotlinType)) } - MethodBridge.ReturnValue.Instance.InitResult, - MethodBridge.ReturnValue.Instance.FactoryResult, - -> SpecialReferenceOirType.InstanceType.toKirType() + if (genericTypeUsage != null) + return genericTypeUsage + } + + val classDescriptor = kotlinType.getErasedTypeClass() + + // TODO: translate `where T : BaseClass, T : SomeInterface` to `BaseClass* ` + + // TODO: expose custom inline class boxes properly. + if (isAny(classDescriptor) || classDescriptor.classId in customTypeMappers.hiddenTypes || classDescriptor.isInlined()) { + return SpecialReferenceOirType.Id.toKirType() + } + + if (classDescriptor.defaultType.isObjCObjectType()) { + return mapObjCObjectReferenceTypeIgnoringNullability(classDescriptor) } - private fun mapType(kotlinType: KotlinType, typeBridge: TypeBridge): KirType = - when (typeBridge) { - ReferenceBridge -> ReferenceKirType(kotlinType) - is BlockPointerBridge -> mapFunctionType(kotlinType, typeBridge) - is ValueTypeBridge -> mapValueType(kotlinType, typeBridge) + // There are number of tricky corner cases getting here. + val kirClass = descriptorKirProvider.findClass(classDescriptor) ?: return SpecialReferenceOirType.Id.toKirType() + + val typeArgs = if (kirClass.kind == KirClass.Kind.Interface) { + emptyList() + } else { + kotlinType.arguments.map { typeProjection -> + mapTypeArgument(typeProjection) + } } - private fun mapFunctionType( - kotlinType: KotlinType, - typeBridge: BlockPointerBridge, - ): KirType { - val expectedDescriptor = kotlinType.builtIns.getFunction(typeBridge.numberOfParameters) + return kirClass.toType(typeArgs) + } + + context(KirTypeParameterScope) + private fun mapTypeIfFlow(kotlinType: KotlinType): UnresolvedFlowKirType? { + val supportedFlow = SupportedFlow.from(kotlinType) ?: return null - // Somewhat similar to mapType: - val functionType = if (TypeUtils.getClassDescriptor(kotlinType) == expectedDescriptor) { - kotlinType + val flowTypeArgument = kotlinType.arguments.single() + + val supportedFlowVariant = if (flowTypeArgument.type.isNullable()) { + supportedFlow.optionalVariant } else { - kotlinType.supertypes().singleOrNull { TypeUtils.getClassDescriptor(it) == expectedDescriptor } - ?: expectedDescriptor.defaultType // Should not happen though. + supportedFlow.requiredVariant } - return BlockPointerKirType(functionType, typeBridge.returnsVoid) + return UnresolvedFlowKirType(supportedFlowVariant) { + mapTypeArgument(flowTypeArgument) + } } - private fun mapValueType( - kotlinType: KotlinType, - typeBridge: ValueTypeBridge, - ): KirType = - when (typeBridge.objCValueType) { - ObjCValueType.BOOL -> PrimitiveOirType.BOOL - ObjCValueType.UNICHAR -> PrimitiveOirType.unichar - ObjCValueType.CHAR -> PrimitiveOirType.int8_t - ObjCValueType.SHORT -> PrimitiveOirType.int16_t - ObjCValueType.INT -> PrimitiveOirType.int32_t - ObjCValueType.LONG_LONG -> PrimitiveOirType.int64_t - ObjCValueType.UNSIGNED_CHAR -> PrimitiveOirType.uint8_t - ObjCValueType.UNSIGNED_SHORT -> PrimitiveOirType.uint16_t - ObjCValueType.UNSIGNED_INT -> PrimitiveOirType.uint32_t - ObjCValueType.UNSIGNED_LONG_LONG -> PrimitiveOirType.uint64_t - ObjCValueType.FLOAT -> PrimitiveOirType.float - ObjCValueType.DOUBLE -> PrimitiveOirType.double - ObjCValueType.POINTER -> PointerOirType(VoidOirType, kotlinType.binaryRepresentationIsNullable()) - }.toKirType() - - private fun OirType.toKirType(): KirType = - OirBasedKirType(this) - - private fun KirType.makeNullableIfReferenceOrPointer(): KirType = - when (this) { - is BlockPointerKirType -> this.copy(kotlinType = kotlinType.makeNullable()) - is OirBasedKirType -> this.makeNullableIfReferenceOrPointer() - is ReferenceKirType -> this.copy(kotlinType = kotlinType.makeNullable()) - is SuspendCompletionKirType -> this.copy(kotlinType = kotlinType.makeNullable()) - ErrorOutKirType -> this + context(KirTypeParameterScope) + private fun KirTypeTranslator.mapTypeArgument(typeProjection: TypeProjection): NonNullReferenceKirType = + if (typeProjection.isStarProjection) { + SpecialReferenceOirType.Id.toKirType() // TODO: use Kotlin upper bound. + } else { + mapReferenceTypeIgnoringNullability(typeProjection.type) + } + + private tailrec fun mapObjCObjectReferenceTypeIgnoringNullability(descriptor: ClassDescriptor): NonNullReferenceKirType { + // TODO: more precise types can be used. + + if (descriptor.isObjCMetaClass()) return SpecialReferenceOirType.Class.toKirType() + if (descriptor.isObjCProtocolClass()) return SpecialReferenceOirType.Protocol.toKirType() + + if (descriptor.isExternalObjCClass() || descriptor.isObjCForwardDeclaration()) { + return descriptorKirProvider.getExternalClass(descriptor).defaultType } - private fun OirBasedKirType.makeNullableIfReferenceOrPointer(): KirType = - when (this.oirType) { - is PointerOirType -> this.oirType.copy(nullable = true).toKirType() - is PrimitiveOirType -> this - VoidOirType -> this - else -> error("Unsupported OirBasedKirType type: $this") + if (descriptor.isKotlinObjCClass()) { + return mapObjCObjectReferenceTypeIgnoringNullability(descriptor.getSuperClassOrAny()) } + + return SpecialReferenceOirType.Id.toKirType() + } + + context(KirTypeParameterScope) + fun mapFunctionType(kotlinType: KotlinType, returnsVoid: Boolean): ReferenceKirType = + mapFunctionTypeIgnoringNullability(kotlinType, returnsVoid).withNullabilityOf(kotlinType) + + context(KirTypeParameterScope) + fun mapFunctionTypeIgnoringNullability( + functionType: KotlinType, + returnsVoid: Boolean, + ): NonNullReferenceKirType { + val parameterTypes = listOfNotNull(functionType.getReceiverTypeFromFunctionType()) + + functionType.getValueParameterTypesFromFunctionType().map { it.type } + + return BlockPointerKirType( + valueParameterTypes = parameterTypes.map { mapReferenceType(it) }, + returnType = if (returnsVoid) { + VoidOirType.toKirType() + } else { + mapReferenceType(functionType.getReturnTypeFromFunctionType()) + }, + ) + } + + private tailrec fun KotlinType.getErasedTypeClass(): ClassDescriptor = + TypeUtils.getClassDescriptor(this) ?: this.constructor.supertypes.first().getErasedTypeClass() } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeTranslatorUtilityScope.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeTranslatorUtilityScope.kt new file mode 100644 index 000000000..2d1cce5c0 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/kir/type/translation/KirTypeTranslatorUtilityScope.kt @@ -0,0 +1,31 @@ +package co.touchlab.skie.kir.type.translation + +import co.touchlab.skie.kir.type.KirType +import co.touchlab.skie.kir.type.NonNullReferenceKirType +import co.touchlab.skie.kir.type.NullableReferenceKirType +import co.touchlab.skie.kir.type.OirBasedKirType +import co.touchlab.skie.kir.type.ReferenceKirType +import co.touchlab.skie.kir.type.SpecialOirKirType +import co.touchlab.skie.oir.type.OirType +import co.touchlab.skie.oir.type.SpecialReferenceOirType +import org.jetbrains.kotlin.backend.konan.binaryRepresentationIsNullable +import org.jetbrains.kotlin.types.KotlinType + +abstract class KirTypeTranslatorUtilityScope { + + protected fun NonNullReferenceKirType.withNullabilityOf(kotlinType: KotlinType): ReferenceKirType = + this.withNullabilityOf(kotlinType.binaryRepresentationIsNullable()) + + protected fun NonNullReferenceKirType.withNullabilityOf(nullable: Boolean): ReferenceKirType = + if (nullable) { + NullableReferenceKirType(this) + } else { + this + } + + protected fun OirType.toKirType(): KirType = + OirBasedKirType(this) + + protected fun SpecialReferenceOirType.toKirType(): SpecialOirKirType = + SpecialOirKirType(this) +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/OirProvider.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/OirProvider.kt index 6e58fa41a..f1703ba9a 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/OirProvider.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/OirProvider.kt @@ -1,51 +1,44 @@ package co.touchlab.skie.oir import co.touchlab.skie.kir.KirProvider -import co.touchlab.skie.kir.descriptor.ExtraDescriptorBuiltins import co.touchlab.skie.kir.element.KirModule -import co.touchlab.skie.oir.builtin.OirBuiltins import co.touchlab.skie.oir.element.OirClass import co.touchlab.skie.oir.element.OirExtension import co.touchlab.skie.oir.element.OirFile import co.touchlab.skie.oir.element.OirModule -import co.touchlab.skie.phases.oir.CreateOirTypesPhase -import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.isInterface class OirProvider( - skieModule: KirModule, - extraDescriptorBuiltins: ExtraDescriptorBuiltins, private val kirProvider: KirProvider, - private val namer: ObjCExportNamer, ) { - lateinit var allKotlinClasses: List + val externalModule = OirModule.External() + + lateinit var kotlinClasses: List private set - lateinit var allKotlinProtocols: List + lateinit var kotlinProtocols: List private set - lateinit var allKotlinClassesAndProtocols: List + lateinit var kotlinClassesAndProtocols: List private set - val allKotlinExtensions: List + val kotlinExtensions: List get() = allFiles.flatMap { it.declarations }.filterIsInstance() - val allExternalClasses: List - get() = allExternalClassesAndProtocols.filter { it.kind == OirClass.Kind.Class } + lateinit var externalClasses: List + private set - val allExternalProtocols: List - get() = allExternalClassesAndProtocols.filter { it.kind == OirClass.Kind.Protocol } + lateinit var externalProtocols: List + private set - val allExternalClassesAndProtocols: Collection - get() = externalClassesAndProtocolsCache.values + lateinit var externalClassesAndProtocols: List + private set val allClasses: List - get() = allKotlinClasses + allExternalClasses + get() = kotlinClasses + externalClasses val allProtocols: List - get() = allKotlinProtocols + allExternalProtocols + get() = kotlinProtocols + externalProtocols val allClassesAndProtocols: List get() = allClasses + allProtocols @@ -57,20 +50,15 @@ class OirProvider( private val fileCache = mutableMapOf, OirFile>() - private val externalClassesAndProtocolsCache = mutableMapOf() - - val skieModule: OirModule.Kotlin = getModule(skieModule) - - val externalModule: OirModule.External by lazy { - OirModule.External() - } - - val oirBuiltins: OirBuiltins by lazy { - OirBuiltins(this, extraDescriptorBuiltins) - } + // TODO Remove after not needed for ApiNotes, do not use to store classes + val skieModule: OirModule.Kotlin = OirModule.Kotlin("Skie") - fun getModule(kirModule: KirModule): OirModule.Kotlin = + fun getKotlinModule(kirModule: KirModule): OirModule.Kotlin = kotlinModuleCache.getOrPut(kirModule) { + assert(kirModule.origin != KirModule.Origin.External) { + "External modules are not supported: $kirModule." + } + OirModule.Kotlin(kirModule.name) } @@ -79,30 +67,17 @@ class OirProvider( OirFile(name, oirModule) } - fun getExternalClass(descriptor: ClassDescriptor): OirClass = - externalClassesAndProtocolsCache.getOrPut(descriptor.original) { - val (name, kind) = if (descriptor.kind.isInterface) { - descriptor.name.asString().removeSuffix("Protocol") to OirClass.Kind.Protocol - } else { - descriptor.name.asString() to OirClass.Kind.Class - } - - val oirClass = OirClass( - name = name, - parent = externalModule, - kind = kind, - origin = OirClass.Origin.CinteropType(descriptor), - ) - - CreateOirTypesPhase.createTypeParameters(oirClass, descriptor.declaredTypeParameters, namer) + fun initializeKotlinClassCache() { + kotlinClassesAndProtocols = kirProvider.kotlinClasses.map { it.oirClass } - oirClass - } + kotlinClasses = kotlinClassesAndProtocols.filter { it.kind == OirClass.Kind.Class } + kotlinProtocols = kotlinClassesAndProtocols.filter { it.kind == OirClass.Kind.Protocol } + } - fun initializeKotlinClassCache() { - allKotlinClassesAndProtocols = kirProvider.allClasses.map { it.oirClass } + fun initializeExternalClassCache() { + externalClassesAndProtocols = kirProvider.allExternalClasses.map { it.oirClass } - allKotlinClasses = allKotlinClassesAndProtocols.filter { it.kind == OirClass.Kind.Class } - allKotlinProtocols = allKotlinClassesAndProtocols.filter { it.kind == OirClass.Kind.Protocol } + externalClasses = externalClassesAndProtocols.filter { it.kind == OirClass.Kind.Class } + externalProtocols = externalClassesAndProtocols.filter { it.kind == OirClass.Kind.Protocol } } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/builtin/OirBuiltins.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/builtin/OirBuiltins.kt deleted file mode 100644 index 7ccaa0bea..000000000 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/builtin/OirBuiltins.kt +++ /dev/null @@ -1,72 +0,0 @@ -package co.touchlab.skie.oir.builtin - -import co.touchlab.skie.kir.descriptor.ExtraDescriptorBuiltins -import co.touchlab.skie.oir.OirProvider -import co.touchlab.skie.oir.element.OirClass -import co.touchlab.skie.oir.element.OirTypeParameter -import co.touchlab.skie.oir.element.toTypeParameterUsage - -@Suppress("PropertyName") -class OirBuiltins( - oirProvider: OirProvider, - extraDescriptorBuiltins: ExtraDescriptorBuiltins, -) { - - val NSObject: OirClass = oirProvider.getExternalClass(extraDescriptorBuiltins.NSObject) - - val NSError: OirClass = oirProvider.getExternalClass(extraDescriptorBuiltins.NSError).apply { - superTypes.add(NSObject.defaultType) - } - - val NSString: OirClass = oirProvider.getExternalClass(extraDescriptorBuiltins.NSString).apply { - superTypes.add(NSObject.defaultType) - } - - val NSArray: OirClass = oirProvider.getExternalClass(extraDescriptorBuiltins.NSArray).apply { - superTypes.add(NSObject.defaultType) - - OirTypeParameter( - name = "E", - parent = this, - variance = OirTypeParameter.Variance.Covariant, - ) - } - - val NSMutableArray: OirClass = oirProvider.getExternalClass(extraDescriptorBuiltins.NSMutableArray).apply { - val typeParameter = OirTypeParameter( - name = "E", - parent = this, - variance = OirTypeParameter.Variance.Covariant, - ) - - val superType = NSArray.toType(typeParameter.toTypeParameterUsage()) - - superTypes.add(superType) - } - - val NSSet: OirClass = oirProvider.getExternalClass(extraDescriptorBuiltins.NSSet).apply { - superTypes.add(NSObject.defaultType) - - OirTypeParameter( - name = "E", - parent = this, - variance = OirTypeParameter.Variance.Covariant, - ) - } - - val NSDictionary: OirClass = oirProvider.getExternalClass(extraDescriptorBuiltins.NSDictionary).apply { - superTypes.add(NSObject.defaultType) - - OirTypeParameter( - name = "K", - parent = this, - variance = OirTypeParameter.Variance.Covariant, - ) - - OirTypeParameter( - name = "V", - parent = this, - variance = OirTypeParameter.Variance.Covariant, - ) - } -} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/element/OirClass.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/element/OirClass.kt index 37119e7f7..0bc087407 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/element/OirClass.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/element/OirClass.kt @@ -4,7 +4,6 @@ import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.oir.type.DeclaredOirType import co.touchlab.skie.oir.type.OirType import co.touchlab.skie.sir.element.SirClass -import org.jetbrains.kotlin.descriptors.ClassDescriptor class OirClass( override val name: String, @@ -15,9 +14,11 @@ class OirClass( lateinit var originalSirClass: SirClass + // Should not be directly accessed before all bridging configuration is done. See @MustBeExecutedAfterBridgingConfiguration. val primarySirClass: SirClass get() = bridgedSirClass ?: originalSirClass + // Should not be directly accessed before all bridging configuration is done. See @MustBeExecutedAfterBridgingConfiguration. var bridgedSirClass: SirClass? = null override val visibility: OirVisibility @@ -58,12 +59,16 @@ class OirClass( sealed interface Origin { - data class CinteropType(val classDescriptor: ClassDescriptor) : Origin - data class Kir(val kirClass: KirClass) : Origin } } +fun KirClass.Kind.toOirKind(): OirClass.Kind = + when (this) { + KirClass.Kind.Interface -> OirClass.Kind.Protocol + else -> OirClass.Kind.Class + } + val OirClass.superClassType: DeclaredOirType? get() = superTypes.firstOrNull { it.declaration.kind == OirClass.Kind.Class } @@ -90,7 +95,3 @@ val OirClass.allSimpleFunctions: List val OirClass.kirClassOrNull: KirClass? get() = (origin as? OirClass.Origin.Kir)?.kirClass - -val OirClass.cinteropClassDescriptorOrNull: ClassDescriptor? - get() = (origin as? OirClass.Origin.CinteropType)?.classDescriptor - diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirCustomTypeMapper.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirCustomTypeMapper.kt deleted file mode 100644 index 8401ba823..000000000 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirCustomTypeMapper.kt +++ /dev/null @@ -1,15 +0,0 @@ -package co.touchlab.skie.oir.type.translation - -import co.touchlab.skie.oir.type.NonNullReferenceOirType -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.types.KotlinType - -interface OirCustomTypeMapper { - - val mappedClassId: ClassId - - fun mapType( - mappedSuperType: KotlinType, - oirTypeParameterScope: OirTypeParameterScope, - ): NonNullReferenceOirType -} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirTypeParameterScope.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirTypeParameterScope.kt deleted file mode 100644 index 03ad5fdb3..000000000 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirTypeParameterScope.kt +++ /dev/null @@ -1,74 +0,0 @@ -package co.touchlab.skie.oir.type.translation - -import co.touchlab.skie.kir.element.KirClass -import co.touchlab.skie.kir.element.KirTypeParameter -import co.touchlab.skie.oir.element.toTypeParameterUsage -import co.touchlab.skie.oir.type.TypeParameterUsageOirType -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.types.KotlinType - -interface OirTypeParameterScope { - - val parent: OirTypeParameterScope? - - fun getTypeParameterUsage(typeParameterDescriptor: TypeParameterDescriptor?): TypeParameterUsageOirType? = - parent?.getTypeParameterUsage(typeParameterDescriptor) - - fun wasTypeAlreadyVisited(type: KotlinType): Boolean = - parent?.wasTypeAlreadyVisited(type) ?: false - - fun deriveFor(type: KotlinType): OirTypeParameterTypeScope? = - OirTypeParameterTypeScope(this, type) - - fun deriveFor(kirClass: KirClass): OirTypeParameterScope = - when (kirClass.kind) { - KirClass.Kind.Class -> OirTypeParameterClassScope(this, kirClass.typeParameters) - else -> this - } -} - -object OirTypeParameterRootScope : OirTypeParameterScope { - - override val parent: OirTypeParameterScope? = null -} - -class OirTypeParameterClassScope( - override val parent: OirTypeParameterScope, - private val typeParameters: List, -) : OirTypeParameterScope { - - override fun getTypeParameterUsage(typeParameterDescriptor: TypeParameterDescriptor?): TypeParameterUsageOirType? { - if (typeParameterDescriptor == null) { - return null - } - - return typeParameters - .firstOrNull { - it.descriptor == typeParameterDescriptor || (it.descriptor.isCapturedFromOuterDeclaration && it.descriptor.original == typeParameterDescriptor) - } - ?.oirTypeParameter - ?.toTypeParameterUsage() - } -} - -class OirTypeParameterTypeScope private constructor( - override val parent: OirTypeParameterScope, - private val type: KotlinType, -) : OirTypeParameterScope { - - override fun wasTypeAlreadyVisited(type: KotlinType): Boolean = - type == this.type || super.wasTypeAlreadyVisited(type) - - companion object { - - operator fun invoke(parent: OirTypeParameterScope, type: KotlinType): OirTypeParameterTypeScope? = - if (parent.wasTypeAlreadyVisited(type)) { - null - } else { - OirTypeParameterTypeScope(parent, type) - } - } -} - -val KirClass.typeParameterScope: OirTypeParameterScope - get() = OirTypeParameterRootScope.deriveFor(this) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirTypeTranslator.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirTypeTranslator.kt index b548055b2..e81d6b119 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirTypeTranslator.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/oir/type/translation/OirTypeTranslator.kt @@ -1,199 +1,55 @@ package co.touchlab.skie.oir.type.translation -import co.touchlab.skie.kir.KirProvider -import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.kir.type.BlockPointerKirType -import co.touchlab.skie.kir.type.ErrorOutKirType +import co.touchlab.skie.kir.type.DeclarationBackedKirType +import co.touchlab.skie.kir.type.DeclaredKirType import co.touchlab.skie.kir.type.KirType +import co.touchlab.skie.kir.type.NonNullReferenceKirType +import co.touchlab.skie.kir.type.NullableReferenceKirType import co.touchlab.skie.kir.type.OirBasedKirType -import co.touchlab.skie.kir.type.ReferenceKirType -import co.touchlab.skie.kir.type.SuspendCompletionKirType -import co.touchlab.skie.oir.OirProvider -import co.touchlab.skie.oir.builtin.OirBuiltins +import co.touchlab.skie.kir.type.PointerKirType +import co.touchlab.skie.kir.type.SpecialOirKirType +import co.touchlab.skie.kir.type.TypeParameterUsageKirType +import co.touchlab.skie.kir.type.UnresolvedFlowKirType +import co.touchlab.skie.oir.element.toTypeParameterUsage import co.touchlab.skie.oir.type.BlockPointerOirType +import co.touchlab.skie.oir.type.DeclaredOirType import co.touchlab.skie.oir.type.NonNullReferenceOirType import co.touchlab.skie.oir.type.NullableReferenceOirType import co.touchlab.skie.oir.type.OirType import co.touchlab.skie.oir.type.PointerOirType -import co.touchlab.skie.oir.type.ReferenceOirType -import co.touchlab.skie.oir.type.SpecialReferenceOirType -import co.touchlab.skie.oir.type.VoidOirType -import org.jetbrains.kotlin.backend.konan.binaryRepresentationIsNullable -import org.jetbrains.kotlin.backend.konan.isExternalObjCClass -import org.jetbrains.kotlin.backend.konan.isInlined -import org.jetbrains.kotlin.backend.konan.isKotlinObjCClass -import org.jetbrains.kotlin.backend.konan.isObjCForwardDeclaration -import org.jetbrains.kotlin.backend.konan.isObjCMetaClass -import org.jetbrains.kotlin.backend.konan.isObjCObjectType -import org.jetbrains.kotlin.backend.konan.isObjCProtocolClass -import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isAny -import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType -import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType -import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.resolve.descriptorUtil.classId -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny -import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.typeUtil.isTypeParameter -import org.jetbrains.kotlin.types.typeUtil.supertypes -// Logic mostly copied from ObjCExportTranslatorImpl +class OirTypeTranslator { -class OirTypeTranslator( - private val kirProvider: KirProvider, - private val oirProvider: OirProvider, - private val oirBuiltins: OirBuiltins, - private val customTypeMappers: OirCustomTypeMappers, -) { - - fun mapType(kirType: KirType, oirTypeParameterScope: OirTypeParameterScope): OirType = + fun mapType(kirType: KirType): OirType = when (kirType) { + is NonNullReferenceKirType -> mapType(kirType) is OirBasedKirType -> kirType.oirType - is ReferenceKirType -> mapType(kirType, oirTypeParameterScope) - is BlockPointerKirType -> mapType(kirType, oirTypeParameterScope) - is SuspendCompletionKirType -> mapType(kirType, oirTypeParameterScope) - ErrorOutKirType -> PointerOirType(oirBuiltins.NSError.defaultType.withNullabilityOf(true), nullable = true) - } - - private fun mapType(kirType: ReferenceKirType, oirTypeParameterScope: OirTypeParameterScope): ReferenceOirType = - mapReferenceType(kirType.kotlinType, oirTypeParameterScope) - - private fun mapType(kirType: BlockPointerKirType, oirTypeParameterScope: OirTypeParameterScope): ReferenceOirType = - mapFunctionTypeIgnoringNullability(kirType.kotlinType, oirTypeParameterScope, kirType.returnsVoid) - .withNullabilityOf(kirType.kotlinType) - - private fun mapType(kirType: SuspendCompletionKirType, oirTypeParameterScope: OirTypeParameterScope): BlockPointerOirType { - val resultType = if (kirType.useUnitCompletion) { - null - } else { - when (val it = mapReferenceType(kirType.kotlinType, oirTypeParameterScope)) { - is NonNullReferenceOirType -> NullableReferenceOirType(it, isNullableResult = false) - is NullableReferenceOirType -> NullableReferenceOirType(it.nonNullType, isNullableResult = true) - } + is PointerKirType -> PointerOirType(mapType(kirType.pointee), kirType.nullable) + is NullableReferenceKirType -> NullableReferenceOirType(mapType(kirType.nonNullType), kirType.isNullableResult) } - return BlockPointerOirType( - valueParameterTypes = listOfNotNull( - resultType, - oirBuiltins.NSError.defaultType.withNullabilityOf(true), - ), - returnType = VoidOirType, - ) - } - - private fun mapReferenceType(kotlinType: KotlinType, oirTypeParameterScope: OirTypeParameterScope): ReferenceOirType = - mapReferenceTypeIgnoringNullability(kotlinType, oirTypeParameterScope).withNullabilityOf(kotlinType) - - fun mapReferenceTypeIgnoringNullability(kotlinType: KotlinType, oirTypeParameterScope: OirTypeParameterScope): NonNullReferenceOirType { - class TypeMappingMatch(val type: KotlinType, val descriptor: ClassDescriptor, val mapper: OirCustomTypeMapper) - - val typeMappingMatches = (listOf(kotlinType) + kotlinType.supertypes()).mapNotNull { type -> - (type.constructor.declarationDescriptor as? ClassDescriptor)?.let { descriptor -> - customTypeMappers.getMapper(descriptor)?.let { mapper -> - TypeMappingMatch(type, descriptor, mapper) - } - } - } - - val mostSpecificMatches = typeMappingMatches.filter { match -> - typeMappingMatches.all { otherMatch -> - otherMatch.descriptor == match.descriptor || - !otherMatch.descriptor.isSubclassOf(match.descriptor) + private fun mapType(kirType: NonNullReferenceKirType): NonNullReferenceOirType = + when (kirType) { + is BlockPointerKirType -> { + BlockPointerOirType( + valueParameterTypes = kirType.valueParameterTypes.map { mapType(it) }, + returnType = mapType(kirType.returnType), + ) } + is DeclarationBackedKirType -> mapType(kirType) + is SpecialOirKirType -> kirType.oirType + is TypeParameterUsageKirType -> kirType.typeParameter.oirTypeParameter.toTypeParameterUsage() } - mostSpecificMatches.firstOrNull()?.let { - val derivedParameterScope = oirTypeParameterScope.deriveFor(it.type) ?: return SpecialReferenceOirType.Id - - return it.mapper.mapType(it.type, derivedParameterScope) - } - - if (kotlinType.isTypeParameter()) { - val genericTypeUsage = oirTypeParameterScope.getTypeParameterUsage(TypeUtils.getTypeParameterDescriptorOrNull(kotlinType)) - - if (genericTypeUsage != null) - return genericTypeUsage - } - - val classDescriptor = kotlinType.getErasedTypeClass() - - // TODO: translate `where T : BaseClass, T : SomeInterface` to `BaseClass* ` - - // TODO: expose custom inline class boxes properly. - if (isAny(classDescriptor) || classDescriptor.classId in customTypeMappers.hiddenTypes || classDescriptor.isInlined()) { - return SpecialReferenceOirType.Id - } - - if (classDescriptor.defaultType.isObjCObjectType()) { - return mapObjCObjectReferenceTypeIgnoringNullability(classDescriptor) - } - - // There are number of tricky corner cases getting here. - val kirClass = kirProvider.findClass(classDescriptor) ?: return SpecialReferenceOirType.Id - - val typeArgs = if (kirClass.kind == KirClass.Kind.Interface) { - emptyList() - } else { - kotlinType.arguments.map { typeProjection -> - if (typeProjection.isStarProjection) { - SpecialReferenceOirType.Id // TODO: use Kotlin upper bound. - } else { - mapReferenceTypeIgnoringNullability(typeProjection.type, oirTypeParameterScope) - } + fun mapType(kirType: DeclarationBackedKirType): DeclaredOirType = + when (kirType) { + is DeclaredKirType -> { + DeclaredOirType( + declaration = kirType.declaration.oirClass, + typeArguments = kirType.typeArguments.map { mapType(it) }, + ) } + is UnresolvedFlowKirType -> error("UnresolvedFlowKirType must be resolved before translation to Oir.") } - - return kirClass.oirClass.toType(typeArgs) - } - - private tailrec fun mapObjCObjectReferenceTypeIgnoringNullability(descriptor: ClassDescriptor): NonNullReferenceOirType { - // TODO: more precise types can be used. - - if (descriptor.isObjCMetaClass()) return SpecialReferenceOirType.Class - if (descriptor.isObjCProtocolClass()) return SpecialReferenceOirType.Protocol - - if (descriptor.isExternalObjCClass() || descriptor.isObjCForwardDeclaration()) { - return oirProvider.getExternalClass(descriptor).defaultType - } - - if (descriptor.isKotlinObjCClass()) { - return mapObjCObjectReferenceTypeIgnoringNullability(descriptor.getSuperClassOrAny()) - } - - return SpecialReferenceOirType.Id - } - - fun mapFunctionTypeIgnoringNullability( - functionType: KotlinType, - oirTypeParameterScope: OirTypeParameterScope, - returnsVoid: Boolean, - ): BlockPointerOirType { - val parameterTypes = listOfNotNull(functionType.getReceiverTypeFromFunctionType()) + - functionType.getValueParameterTypesFromFunctionType().map { it.type } - - return BlockPointerOirType( - valueParameterTypes = parameterTypes.map { mapReferenceType(it, oirTypeParameterScope) }, - returnType = if (returnsVoid) { - VoidOirType - } else { - mapReferenceType(functionType.getReturnTypeFromFunctionType(), oirTypeParameterScope) - }, - ) - } - - private fun NonNullReferenceOirType.withNullabilityOf(kotlinType: KotlinType): ReferenceOirType = - this.withNullabilityOf(kotlinType.binaryRepresentationIsNullable()) - - private fun NonNullReferenceOirType.withNullabilityOf(nullable: Boolean): ReferenceOirType = - if (nullable) { - NullableReferenceOirType(this) - } else { - this - } - - private tailrec fun KotlinType.getErasedTypeClass(): ClassDescriptor = - TypeUtils.getClassDescriptor(this) ?: this.constructor.supertypes.first().getErasedTypeClass() } - diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/BackgroundPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/BackgroundPhase.kt new file mode 100644 index 000000000..57e185ae8 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/BackgroundPhase.kt @@ -0,0 +1,10 @@ +package co.touchlab.skie.phases + +// Can run in parallel with the Kotlin compiler and other SKIE phases, cannot use anything from the shared context that is not thread-safe +interface BackgroundPhase : ScheduledPhase { + + interface Context : ScheduledPhase.Context { + + override val context: Context + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ClassExportPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ClassExportPhase.kt index 5e17d29ad..91dfdcf0c 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ClassExportPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ClassExportPhase.kt @@ -1,13 +1,16 @@ package co.touchlab.skie.phases +import co.touchlab.skie.kir.descriptor.MutableDescriptorProvider import co.touchlab.skie.kir.irbuilder.DeclarationBuilder -interface ClassExportPhase : SkiePhase { +interface ClassExportPhase : ForegroundPhase { - interface Context : SkiePhase.Context { + interface Context : ForegroundPhase.Context { override val context: Context + override val descriptorProvider: MutableDescriptorProvider + val declarationBuilder: DeclarationBuilder } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/CommonSkieContext.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/CommonSkieContext.kt new file mode 100644 index 000000000..ab745c968 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/CommonSkieContext.kt @@ -0,0 +1,41 @@ +package co.touchlab.skie.phases + +import co.touchlab.skie.configuration.RootConfiguration +import co.touchlab.skie.configuration.SkieConfigurationFlag +import co.touchlab.skie.configuration.provider.CompilerSkieConfigurationData +import co.touchlab.skie.phases.analytics.performance.SkiePerformanceAnalytics +import co.touchlab.skie.plugin.analytics.AnalyticsCollector +import co.touchlab.skie.util.FrameworkLayout +import co.touchlab.skie.util.Reporter +import co.touchlab.skie.util.directory.SkieBuildDirectory +import co.touchlab.skie.util.directory.SkieDirectories + +interface CommonSkieContext { + + val context: CommonSkieContext + + val skiePhaseScheduler: SkiePhaseScheduler + + val skieConfigurationData: CompilerSkieConfigurationData + + val rootConfiguration: RootConfiguration + + val skieDirectories: SkieDirectories + + val framework: FrameworkLayout + + val analyticsCollector: AnalyticsCollector + + val skiePerformanceAnalyticsProducer: SkiePerformanceAnalytics.Producer + + val reporter: Reporter + + val skieBuildDirectory: SkieBuildDirectory + get() = skieDirectories.buildDirectory + + val SkieConfigurationFlag.isEnabled: Boolean + get() = rootConfiguration.isFlagEnabled(this) + + val SkieConfigurationFlag.isDisabled: Boolean + get() = this.isEnabled.not() +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/DescriptorConversionPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/DescriptorConversionPhase.kt new file mode 100644 index 000000000..6caea62d7 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/DescriptorConversionPhase.kt @@ -0,0 +1,31 @@ +package co.touchlab.skie.phases + +import co.touchlab.skie.kir.KirProvider +import co.touchlab.skie.kir.builtin.KirBuiltins +import co.touchlab.skie.kir.descriptor.DescriptorKirProvider +import co.touchlab.skie.kir.descriptor.ObjCExportedInterfaceProvider +import co.touchlab.skie.kir.type.translation.KirDeclarationTypeTranslator +import co.touchlab.skie.kir.type.translation.KirTypeTranslator +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer + +interface DescriptorConversionPhase : ForegroundPhase { + + interface Context : ForegroundPhase.Context { + + override val context: Context + + val kirProvider: KirProvider + + val descriptorKirProvider: DescriptorKirProvider + + val kirBuiltins: KirBuiltins + + val namer: ObjCExportNamer + + val kirTypeTranslator: KirTypeTranslator + + val kirDeclarationTypeTranslator: KirDeclarationTypeTranslator + + val objCExportedInterfaceProvider: ObjCExportedInterfaceProvider + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/DescriptorModificationPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/DescriptorModificationPhase.kt index 809a55e1f..1df7b73f7 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/DescriptorModificationPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/DescriptorModificationPhase.kt @@ -2,9 +2,9 @@ package co.touchlab.skie.phases import co.touchlab.skie.kir.irbuilder.DeclarationBuilder -interface DescriptorModificationPhase : SkiePhase { +interface DescriptorModificationPhase : ForegroundPhase { - interface Context : SkiePhase.Context { + interface Context : ForegroundPhase.Context { override val context: Context diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SkiePhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ForegroundPhase.kt similarity index 76% rename from SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SkiePhase.kt rename to SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ForegroundPhase.kt index b9c67d18a..e367b5e30 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SkiePhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ForegroundPhase.kt @@ -1,5 +1,6 @@ package co.touchlab.skie.phases +import co.touchlab.skie.configuration.provider.descriptor.DescriptorConfigurationProvider import co.touchlab.skie.kir.descriptor.DescriptorProvider import co.touchlab.skie.kir.descriptor.ExtraDescriptorBuiltins import co.touchlab.skie.kir.descriptor.cache.CachedObjCExportMapper @@ -7,24 +8,17 @@ import org.jetbrains.kotlin.backend.konan.KonanConfig import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.konan.target.AppleConfigurables -interface SkiePhase { +interface ForegroundPhase : ScheduledPhase { - context(C) - fun isActive(): Boolean = true - - context(C) - suspend fun execute() - - interface Context : InitPhase.Context { + interface Context : ScheduledPhase.Context { override val context: Context - val konanConfig: KonanConfig + val descriptorProvider: DescriptorProvider - val configurables: AppleConfigurables - get() = konanConfig.platform.configurables as AppleConfigurables + val descriptorConfigurationProvider: DescriptorConfigurationProvider - val descriptorProvider: DescriptorProvider + val konanConfig: KonanConfig val mapper: CachedObjCExportMapper get() = descriptorProvider.mapper @@ -35,6 +29,7 @@ interface SkiePhase { val extraDescriptorBuiltins: ExtraDescriptorBuiltins get() = descriptorProvider.extraDescriptorBuiltins - fun launch(action: suspend () -> Unit) + val configurables: AppleConfigurables + get() = konanConfig.platform.configurables as AppleConfigurables } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/InitPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/InitPhase.kt index a09bf72df..faf64d551 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/InitPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/InitPhase.kt @@ -1,73 +1,13 @@ package co.touchlab.skie.phases -import co.touchlab.skie.configuration.RootConfiguration -import co.touchlab.skie.configuration.SkieConfigurationFlag -import co.touchlab.skie.configuration.provider.CompilerSkieConfigurationData -import co.touchlab.skie.configuration.provider.descriptor.DescriptorConfigurationProvider -import co.touchlab.skie.phases.analytics.performance.SkiePerformanceAnalytics -import co.touchlab.skie.phases.swift.SwiftCompilerConfiguration -import co.touchlab.skie.plugin.analytics.AnalyticsCollector -import co.touchlab.skie.util.FrameworkLayout -import co.touchlab.skie.util.Reporter -import co.touchlab.skie.util.directory.SkieBuildDirectory -import co.touchlab.skie.util.directory.SkieDirectories import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.CompilerConfigurationKey object InitPhase { - interface Context { + interface Context : CommonSkieContext { - val context: Context - - val skiePhaseScheduler: SkiePhaseScheduler + override val context: Context val compilerConfiguration: CompilerConfiguration - - val skieConfigurationData: CompilerSkieConfigurationData - - val descriptorConfigurationProvider: DescriptorConfigurationProvider - - val rootConfiguration: RootConfiguration - - val swiftCompilerConfiguration: SwiftCompilerConfiguration - - val skieDirectories: SkieDirectories - - val framework: FrameworkLayout - - val analyticsCollector: AnalyticsCollector - - val skiePerformanceAnalyticsProducer: SkiePerformanceAnalytics.Producer - - val reporter: Reporter - - val skieBuildDirectory: SkieBuildDirectory - get() = skieDirectories.buildDirectory - - fun get(key: CompilerConfigurationKey): T = - compilerConfiguration.getNotNull(key) - - fun getOrNull(key: CompilerConfigurationKey): T? = - compilerConfiguration.get(key) - - fun getOrCreate(key: CompilerConfigurationKey, defaultValue: () -> T): T = - getOrNull(key) ?: run { - val value = defaultValue() - - put(key, value) - - value - } - - fun put(key: CompilerConfigurationKey, value: T) { - compilerConfiguration.put(key, value) - } - - val SkieConfigurationFlag.isEnabled: Boolean - get() = rootConfiguration.isFlagEnabled(this) - - val SkieConfigurationFlag.isDisabled: Boolean - get() = this.isEnabled.not() } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/KotlinIrPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/KotlinIrPhase.kt index 514dc7d41..715514a64 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/KotlinIrPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/KotlinIrPhase.kt @@ -6,9 +6,9 @@ import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -interface KotlinIrPhase : SkiePhase { +interface KotlinIrPhase : ForegroundPhase { - interface Context : SkiePhase.Context { + interface Context : ForegroundPhase.Context { override val context: Context diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/LinkPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/LinkPhase.kt index 18fc5f277..ffa9ea318 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/LinkPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/LinkPhase.kt @@ -1,13 +1,16 @@ package co.touchlab.skie.phases +import co.touchlab.skie.kir.descriptor.DescriptorKirProvider import java.nio.file.Path -interface LinkPhase : SkiePhase { +interface LinkPhase : ForegroundPhase { - interface Context : SkiePhase.Context { + interface Context : ForegroundPhase.Context { override val context: Context + val descriptorKirProvider: DescriptorKirProvider + fun link(additionalObjectFiles: List) suspend fun awaitAllBackgroundJobs() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ScheduledPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ScheduledPhase.kt new file mode 100644 index 000000000..408a9459e --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/ScheduledPhase.kt @@ -0,0 +1,26 @@ +package co.touchlab.skie.phases + +import co.touchlab.skie.phases.util.StatefulScheduledPhase +import co.touchlab.skie.util.SwiftCompilerConfiguration + +interface ScheduledPhase { + + context(C) + fun isActive(): Boolean = true + + context(C) + suspend fun execute() + + interface Context : CommonSkieContext { + + override val context: Context + + val swiftCompilerConfiguration: SwiftCompilerConfiguration + + fun launch(action: suspend () -> Unit) + + fun storeStatefulScheduledPhaseBody(phase: StatefulScheduledPhase, action: CONTEXT.() -> Unit) + + fun executeStatefulScheduledPhase(phase: StatefulScheduledPhase, context: CONTEXT) + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SirPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SirPhase.kt index dda89fb77..454d988cf 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SirPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SirPhase.kt @@ -2,10 +2,7 @@ package co.touchlab.skie.phases import co.touchlab.skie.kir.KirProvider import co.touchlab.skie.kir.builtin.KirBuiltins -import co.touchlab.skie.kir.descriptor.ObjCExportedInterfaceProvider -import co.touchlab.skie.kir.type.translation.KirTypeTranslator import co.touchlab.skie.oir.OirProvider -import co.touchlab.skie.oir.builtin.OirBuiltins import co.touchlab.skie.oir.type.translation.OirTypeTranslator import co.touchlab.skie.phases.oir.util.ExternalApiNotesProvider import co.touchlab.skie.sir.ClassNamespaceProvider @@ -13,11 +10,10 @@ import co.touchlab.skie.sir.SirFileProvider import co.touchlab.skie.sir.SirProvider import co.touchlab.skie.sir.builtin.SirBuiltins import co.touchlab.skie.sir.type.translation.SirTypeTranslator -import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer -interface SirPhase : SkiePhase { +interface SirPhase : BackgroundPhase { - interface Context : SkiePhase.Context { + interface Context : BackgroundPhase.Context { override val context: Context @@ -31,22 +27,14 @@ interface SirPhase : SkiePhase { val kirBuiltins: KirBuiltins - val oirBuiltins: OirBuiltins - val sirBuiltins: SirBuiltins val classNamespaceProvider: ClassNamespaceProvider val externalApiNotesProvider: ExternalApiNotesProvider - val namer: ObjCExportNamer - - val kirTypeTranslator: KirTypeTranslator - val oirTypeTranslator: OirTypeTranslator val sirTypeTranslator: SirTypeTranslator - - val objCExportedInterfaceProvider: ObjCExportedInterfaceProvider } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SkiePhaseScheduler.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SkiePhaseScheduler.kt index 58c82d48b..7f1c83862 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SkiePhaseScheduler.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SkiePhaseScheduler.kt @@ -26,21 +26,24 @@ import co.touchlab.skie.phases.header.DeclareSkieErrorTypesPhase import co.touchlab.skie.phases.header.FixForwardDeclarationsPhase import co.touchlab.skie.phases.header.FixHeaderFilePropertyOrderingPhase import co.touchlab.skie.phases.header.GenerateFakeObjCDependenciesPhase +import co.touchlab.skie.phases.kir.CreateExposedKirTypesPhase import co.touchlab.skie.phases.kir.CreateKirMembersPhase -import co.touchlab.skie.phases.kir.CreateKirTypesPhase import co.touchlab.skie.phases.memberconflicts.RenameCallableDeclarationsConflictingWithTypeDeclarationsPhase import co.touchlab.skie.phases.memberconflicts.RenameConflictingCallableDeclarationsPhase import co.touchlab.skie.phases.memberconflicts.RenameParametersNamedSelfPhase import co.touchlab.skie.phases.oir.ConfigureCInteropFrameworkNameForPlatformTypesPhase import co.touchlab.skie.phases.oir.ConfigureExternalOirTypesBridgingPhase +import co.touchlab.skie.phases.oir.CreateExternalOirTypesPhase import co.touchlab.skie.phases.oir.CreateFakeObjCConstructorsPhase +import co.touchlab.skie.phases.oir.CreateKotlinOirTypesPhase import co.touchlab.skie.phases.oir.CreateOirMembersPhase -import co.touchlab.skie.phases.oir.CreateOirTypesPhase import co.touchlab.skie.phases.oir.FixOirFunctionSignaturesForApiNotesPhase +import co.touchlab.skie.phases.oir.InitializeOirSuperTypesPhase import co.touchlab.skie.phases.other.AddAvailabilityBasedDeprecationLevelPhase import co.touchlab.skie.phases.other.AddAvailabilityToAsyncFunctionsPhase import co.touchlab.skie.phases.other.AddFoundationImportsPhase import co.touchlab.skie.phases.other.AwaitAllBackgroundJobsPhase +import co.touchlab.skie.phases.other.ConfigureSwiftSpecificLinkerArgsPhase import co.touchlab.skie.phases.other.DeclareMissingSymbolsPhase import co.touchlab.skie.phases.other.DeleteSkieFrameworkContentPhase import co.touchlab.skie.phases.other.ExtraClassExportPhase @@ -49,6 +52,7 @@ import co.touchlab.skie.phases.other.FixLibrariesShortNamePhase import co.touchlab.skie.phases.other.GenerateModulemapFilePhase import co.touchlab.skie.phases.other.LinkObjectFilesPhase import co.touchlab.skie.phases.other.LoadCustomSwiftSourceFilesPhase +import co.touchlab.skie.phases.other.ProcessReportedMessagesPhase import co.touchlab.skie.phases.other.VerifyMinOSVersionPhase import co.touchlab.skie.phases.other.VerifyModuleNamePhase import co.touchlab.skie.phases.other.VerifyNoBitcodeEmbeddingPhase @@ -65,7 +69,7 @@ import co.touchlab.skie.phases.sir.type.CreateKotlinSirExtensionsPhase import co.touchlab.skie.phases.sir.type.CreateKotlinSirTypesPhase import co.touchlab.skie.phases.sir.type.CreateStableNameTypeAliasesPhase import co.touchlab.skie.phases.sir.type.FixNamesOfInaccessibleNestedClassesPhase -import co.touchlab.skie.phases.sir.type.InitializeSirTypesSuperTypesForOirPhase +import co.touchlab.skie.phases.sir.type.InitializeSirSuperTypesPhase import co.touchlab.skie.phases.swift.CompileSwiftPhase import co.touchlab.skie.phases.swift.ConvertSirIrFilesToSourceFilesPhase import co.touchlab.skie.phases.swift.ConvertSirSourceFilesToCompilableFilesPhase @@ -75,6 +79,7 @@ import co.touchlab.skie.phases.typeconflicts.RenameTypesConflictingWithKotlinMod import co.touchlab.skie.phases.typeconflicts.RenameTypesConflictsWithOtherTypesPhase import co.touchlab.skie.phases.typeconflicts.TemporarilyRenameTypesConflictingWithExternalModulesPhase import co.touchlab.skie.phases.util.SkiePhaseGroup +import co.touchlab.skie.phases.util.run import co.touchlab.skie.util.addAll class SkiePhaseScheduler { @@ -110,32 +115,47 @@ class SkiePhaseScheduler { ) } - val sirPhases = SkiePhaseGroup { context -> + val descriptorConversionPhases = SkiePhaseGroup { context -> addAll( - // Debug(before) - VerifyDescriptorProviderConsistencyPhase, - DumpSwiftApiPhase.BeforeApiNotes, - - // IR Setup - CreateKirTypesPhase(context), + CreateExposedKirTypesPhase(context), CreateKirMembersPhase(context), - // Flows -> + // Flows UnifyFlowConfigurationForOverridesPhase(context), SuspendGenerator.FlowMappingConfigurationPhase, ConvertFlowsPhase(context), - // <- Flows - CreateOirTypesPhase(context), + ExtraClassExportPhase.HideExportFunctionsInitPhase, + + DefaultArgumentGenerator.RegisterOverloadsPhase, + DefaultArgumentGenerator.RemoveManglingOfOverloadsInitPhase, + + SuspendGenerator.KotlinBridgingFunctionVisibilityConfigurationInitPhase, + SuspendGenerator.SwiftBridgeGeneratorInitPhase, + ) + } + + val sirPhases = SkiePhaseGroup { context -> + addAll( + // Debug(before) + + DumpSwiftApiPhase.BeforeApiNotes, + + // IR Setup + + CreateKotlinOirTypesPhase(context), + CreateExternalOirTypesPhase, + InitializeOirSuperTypesPhase, + CreateOirMembersPhase(context), ConfigureCInteropFrameworkNameForPlatformTypesPhase, - CreateKotlinSirTypesPhase(context), + CreateKotlinSirTypesPhase, CreateKotlinSirExtensionsPhase, CreateExternalSirTypesPhase, - InitializeSirTypesSuperTypesForOirPhase, + InitializeSirSuperTypesPhase, ConfigureExternalOirTypesBridgingPhase(context), ConfigureStableNameTypeAliasesForKotlinRuntimePhase, @@ -160,14 +180,13 @@ class SkiePhaseScheduler { // Features - ExtraClassExportPhase.FinalizePhase, + ExtraClassExportPhase.HideExportFunctionsFinalizePhase, - DefaultArgumentGenerator.RegisterOverloadsPhase, - DefaultArgumentGenerator.RemoveManglingOfOverloadsPhase, + DefaultArgumentGenerator.RemoveManglingOfOverloadsFinalizePhase, RemoveConflictingDefaultArgumentOverloadsPhase, - SuspendGenerator.KotlinBridgingFunctionVisibilityConfigurationPhase, - SuspendGenerator.SwiftBridgeGeneratorPhase, + SuspendGenerator.KotlinBridgingFunctionVisibilityConfigurationFinalizePhase, + SuspendGenerator.SwiftBridgeGeneratorFinalizePhase, FlowBridgingConfigurationPhase, FlowConversionConstructorsGenerator(context), @@ -223,38 +242,45 @@ class SkiePhaseScheduler { val linkPhases = SkiePhaseGroup { context -> addAll( + ConfigureSwiftSpecificLinkerArgsPhase, AwaitAllBackgroundJobsPhase, LinkObjectFilesPhase, + ProcessReportedMessagesPhase, LogSkiePerformanceAnalyticsPhase, ) } - context(SkiePhase.Context) + context(ScheduledPhase.Context) fun runClassExportPhases(contextFactory: () -> ClassExportPhase.Context) { classExportPhases.run(contextFactory) } - context(SkiePhase.Context) + context(ScheduledPhase.Context) fun runDescriptorModificationPhases(contextFactory: () -> DescriptorModificationPhase.Context) { descriptorModificationPhases.run(contextFactory) } - context(SkiePhase.Context) + context(ScheduledPhase.Context) fun runSymbolTablePhases(contextFactory: () -> SymbolTablePhase.Context) { symbolTablePhases.run(contextFactory) } - context(SkiePhase.Context) + context(ScheduledPhase.Context) fun runKotlinIrPhases(contextFactory: () -> KotlinIrPhase.Context) { kotlinIrPhases.run(contextFactory) } - context(SkiePhase.Context) - fun launchSirPhases(contextFactory: () -> SirPhase.Context) { - sirPhases.launch(contextFactory) + context(ScheduledPhase.Context) + fun runDescriptorConversionPhases(contextFactory: () -> DescriptorConversionPhase.Context) { + descriptorConversionPhases.run(contextFactory) + } + + context(ScheduledPhase.Context) + fun runSirPhases(contextFactory: () -> SirPhase.Context) { + sirPhases.run(contextFactory) } - context(SkiePhase.Context) + context(ScheduledPhase.Context) fun runLinkPhases(contextFactory: () -> LinkPhase.Context) { linkPhases.run(contextFactory) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SymbolTablePhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SymbolTablePhase.kt index eee2dcba6..2117044ad 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SymbolTablePhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/SymbolTablePhase.kt @@ -3,9 +3,9 @@ package co.touchlab.skie.phases import co.touchlab.skie.kir.irbuilder.impl.DeclarationBuilderImpl import co.touchlab.skie.kir.util.SkieSymbolTable -interface SymbolTablePhase : SkiePhase { +interface SymbolTablePhase : ForegroundPhase { - interface Context : SkiePhase.Context { + interface Context : ForegroundPhase.Context { override val context: Context diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/analytics/performance/SkiePerformanceAnalytics.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/analytics/performance/SkiePerformanceAnalytics.kt index 377f1ebb1..bfa43d307 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/analytics/performance/SkiePerformanceAnalytics.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/analytics/performance/SkiePerformanceAnalytics.kt @@ -21,7 +21,7 @@ object SkiePerformanceAnalytics { private val rootConfiguration: RootConfiguration, ) : AnalyticsProducer { - val dispatcher: CoroutineContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + private val dispatcher: CoroutineContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher() override val name: String = "skie-performance" diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/apinotes/MoveBridgesToTopLevelPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/apinotes/MoveBridgesToTopLevelPhase.kt index dfe9d358f..d011b4369 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/apinotes/MoveBridgesToTopLevelPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/apinotes/MoveBridgesToTopLevelPhase.kt @@ -13,7 +13,7 @@ object MoveBridgesToTopLevelPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - kirProvider.allClasses + kirProvider.kotlinClasses .mapNotNull { it.bridgedSirClass } .forEach { it.moveToTopLevel() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/apinotes/builder/ApiNotesFactory.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/apinotes/builder/ApiNotesFactory.kt index a7a24606f..c583bc218 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/apinotes/builder/ApiNotesFactory.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/apinotes/builder/ApiNotesFactory.kt @@ -17,8 +17,8 @@ class ApiNotesFactory( fun create(): ApiNotes = ApiNotes( moduleName = framework.moduleName, - classes = oirProvider.allKotlinClasses.map { it.toApiNote() }, - protocols = oirProvider.allKotlinProtocols.map { it.toApiNote() }, + classes = oirProvider.kotlinClasses.map { it.toApiNote() }, + protocols = oirProvider.kotlinProtocols.map { it.toApiNote() }, ) context(SirPhase.Context) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/debug/VerifyDescriptorProviderConsistencyPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/debug/VerifyDescriptorProviderConsistencyPhase.kt index afb12c2ab..2e524ef72 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/debug/VerifyDescriptorProviderConsistencyPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/debug/VerifyDescriptorProviderConsistencyPhase.kt @@ -3,15 +3,15 @@ package co.touchlab.skie.phases.debug import co.touchlab.skie.configuration.SkieConfigurationFlag -import co.touchlab.skie.phases.SirPhase +import co.touchlab.skie.phases.DescriptorConversionPhase import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe -object VerifyDescriptorProviderConsistencyPhase : SirPhase { +object VerifyDescriptorProviderConsistencyPhase : DescriptorConversionPhase { - context(SirPhase.Context) + context(DescriptorConversionPhase.Context) override fun isActive(): Boolean = SkieConfigurationFlag.Debug_VerifyDescriptorProviderConsistency.isEnabled - context(SirPhase.Context) + context(DescriptorConversionPhase.Context) override suspend fun execute() { val objCExportedInterface = objCExportedInterfaceProvider.objCExportedInterface diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/DefaultArgumentGenerator.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/DefaultArgumentGenerator.kt index f02a9a750..f4f72f666 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/DefaultArgumentGenerator.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/DefaultArgumentGenerator.kt @@ -5,6 +5,7 @@ import co.touchlab.skie.phases.features.defaultarguments.delegate.ClassMethodsDe import co.touchlab.skie.phases.features.defaultarguments.delegate.ConstructorsDefaultArgumentGeneratorDelegate import co.touchlab.skie.phases.features.defaultarguments.delegate.ExtensionFunctionDefaultArgumentGeneratorDelegate import co.touchlab.skie.phases.features.defaultarguments.delegate.TopLevelFunctionDefaultArgumentGeneratorDelegate +import co.touchlab.skie.phases.util.StatefulDescriptorConversionPhase import co.touchlab.skie.phases.util.StatefulSirPhase import co.touchlab.skie.util.SharedCounter @@ -28,7 +29,9 @@ class DefaultArgumentGenerator( } } - object RegisterOverloadsPhase : StatefulSirPhase() + object RegisterOverloadsPhase : StatefulDescriptorConversionPhase() - object RemoveManglingOfOverloadsPhase : StatefulSirPhase() + object RemoveManglingOfOverloadsInitPhase : StatefulDescriptorConversionPhase() + + object RemoveManglingOfOverloadsFinalizePhase : StatefulSirPhase() } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/RemoveConflictingDefaultArgumentOverloadsPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/RemoveConflictingDefaultArgumentOverloadsPhase.kt index 293b5948f..4b0193ee1 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/RemoveConflictingDefaultArgumentOverloadsPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/RemoveConflictingDefaultArgumentOverloadsPhase.kt @@ -14,7 +14,7 @@ object RemoveConflictingDefaultArgumentOverloadsPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - val allBaseFunctions = kirProvider.allConstructors + kirProvider.allSimpleFunctions.filter { it.overriddenDeclarations.isEmpty() } + val allBaseFunctions = kirProvider.kotlinConstructors + kirProvider.kotlinSimpleFunctions.filter { it.overriddenDeclarations.isEmpty() } val allDefaultArgumentOverloads = allBaseFunctions.flatMap { it.defaultArgumentsOverloads }.toSet() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/BaseDefaultArgumentGeneratorDelegate.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/BaseDefaultArgumentGeneratorDelegate.kt index f995ac4d7..f10930fa3 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/BaseDefaultArgumentGeneratorDelegate.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/BaseDefaultArgumentGeneratorDelegate.kt @@ -6,7 +6,6 @@ import co.touchlab.skie.configuration.provider.descriptor.configuration import co.touchlab.skie.kir.descriptor.DescriptorProvider import co.touchlab.skie.kir.irbuilder.DeclarationBuilder import co.touchlab.skie.phases.DescriptorModificationPhase -import co.touchlab.skie.phases.SkiePhase import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope @@ -34,13 +33,13 @@ abstract class BaseDefaultArgumentGeneratorDelegate( private val isInteropEnabledForExternalModules: Boolean = SkieConfigurationFlag.Feature_DefaultArgumentsInExternalLibraries in context.rootConfiguration.enabledFlags - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) protected val FunctionDescriptor.isInteropEnabled: Boolean get() = this.configuration[DefaultArgumentInterop.Enabled] && this.satisfiesMaximumDefaultArgumentCount && (descriptorProvider.isFromLocalModule(this) || isInteropEnabledForExternalModules) - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) private val FunctionDescriptor.satisfiesMaximumDefaultArgumentCount: Boolean get() = this.defaultArgumentCount <= this.configuration[DefaultArgumentInterop.MaximumDefaultArgumentCount] diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/BaseFunctionDefaultArgumentGeneratorDelegate.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/BaseFunctionDefaultArgumentGeneratorDelegate.kt index 1e8101f4f..ee15e43dc 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/BaseFunctionDefaultArgumentGeneratorDelegate.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/BaseFunctionDefaultArgumentGeneratorDelegate.kt @@ -8,7 +8,6 @@ import co.touchlab.skie.kir.irbuilder.util.copyIndexing import co.touchlab.skie.kir.irbuilder.util.copyWithoutDefaultValue import co.touchlab.skie.phases.DescriptorModificationPhase import co.touchlab.skie.phases.KotlinIrPhase -import co.touchlab.skie.phases.SkiePhase import co.touchlab.skie.phases.features.defaultarguments.DefaultArgumentGenerator import co.touchlab.skie.phases.util.doInPhase import co.touchlab.skie.util.SharedCounter @@ -34,7 +33,7 @@ abstract class BaseFunctionDefaultArgumentGeneratorDelegate( private val sharedCounter: SharedCounter, ) : BaseDefaultArgumentGeneratorDelegate(context) { - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) override fun generate() { descriptorProvider.allSupportedFunctions() .filter { it.isInteropEnabled } @@ -47,14 +46,14 @@ abstract class BaseFunctionDefaultArgumentGeneratorDelegate( protected abstract fun DescriptorProvider.allSupportedFunctions(): List - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) private fun generateOverloads(function: SimpleFunctionDescriptor) { function.forEachDefaultArgumentOverload { overloadParameters -> generateOverload(function, overloadParameters) } } - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) private fun generateOverload( function: SimpleFunctionDescriptor, parameters: List, @@ -66,7 +65,7 @@ abstract class BaseFunctionDefaultArgumentGeneratorDelegate( removeManglingOfOverload(newFunction, function) } - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) private fun generateOverloadWithUniqueName( function: SimpleFunctionDescriptor, parameters: List, @@ -127,19 +126,21 @@ abstract class BaseFunctionDefaultArgumentGeneratorDelegate( private fun registerOverload(overloadDescriptor: FunctionDescriptor, function: SimpleFunctionDescriptor) { context.doInPhase(DefaultArgumentGenerator.RegisterOverloadsPhase) { - val overloadKirFunction = kirProvider.getFunction(overloadDescriptor) + val overloadKirFunction = descriptorKirProvider.getFunction(overloadDescriptor) - kirProvider.getFunction(function).defaultArgumentsOverloads.add(overloadKirFunction) + descriptorKirProvider.getFunction(function).defaultArgumentsOverloads.add(overloadKirFunction) } } private fun removeManglingOfOverload(overloadDescriptor: FunctionDescriptor, function: SimpleFunctionDescriptor) { - context.doInPhase(DefaultArgumentGenerator.RemoveManglingOfOverloadsPhase) { - val overloadFunction = kirProvider.getFunction(overloadDescriptor) - val baseFunction = kirProvider.getFunction(function) + context.doInPhase(DefaultArgumentGenerator.RemoveManglingOfOverloadsInitPhase) { + val overloadFunction = descriptorKirProvider.getFunction(overloadDescriptor) + val baseFunction = descriptorKirProvider.getFunction(function) - overloadFunction.originalSirFunction.identifier = baseFunction.originalSirFunction.identifier - overloadFunction.primarySirFunction.identifier = baseFunction.primarySirFunction.identifier + doInPhase(DefaultArgumentGenerator.RemoveManglingOfOverloadsFinalizePhase) { + overloadFunction.originalSirFunction.identifier = baseFunction.originalSirFunction.identifier + overloadFunction.primarySirFunction.identifier = baseFunction.primarySirFunction.identifier + } } } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/ConstructorsDefaultArgumentGeneratorDelegate.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/ConstructorsDefaultArgumentGeneratorDelegate.kt index 58467c40f..f52fb496d 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/ConstructorsDefaultArgumentGeneratorDelegate.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/ConstructorsDefaultArgumentGeneratorDelegate.kt @@ -7,7 +7,6 @@ import co.touchlab.skie.kir.irbuilder.getNamespace import co.touchlab.skie.kir.irbuilder.util.copyWithoutDefaultValue import co.touchlab.skie.phases.DescriptorModificationPhase import co.touchlab.skie.phases.KotlinIrPhase -import co.touchlab.skie.phases.SkiePhase import co.touchlab.skie.phases.features.defaultarguments.DefaultArgumentGenerator import co.touchlab.skie.phases.util.doInPhase import co.touchlab.skie.util.SharedCounter @@ -32,7 +31,7 @@ class ConstructorsDefaultArgumentGeneratorDelegate( private val sharedCounter: SharedCounter, ) : BaseDefaultArgumentGeneratorDelegate(context) { - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) override fun generate() { descriptorProvider.allSupportedClasses.forEach { classDescriptor -> classDescriptor.allSupportedConstructors.forEach { @@ -47,13 +46,13 @@ class ConstructorsDefaultArgumentGeneratorDelegate( private val ClassDescriptor.isSupported: Boolean get() = this.kind == ClassKind.CLASS - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) private val ClassDescriptor.allSupportedConstructors: List get() = descriptorProvider.getExposedConstructors(this) .filter { it.isInteropEnabled } .filter { it.hasDefaultArguments } - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) private fun generateOverloads(constructor: ClassConstructorDescriptor, classDescriptor: ClassDescriptor) { constructor.forEachDefaultArgumentOverload { overloadParameters -> if (overloadParameters.isNotEmpty() || classDescriptor.generateOverloadWithNoParameters) { @@ -69,14 +68,14 @@ class ConstructorsDefaultArgumentGeneratorDelegate( private val ClassConstructorDescriptor.hasNoParametersIgnoringDefaultArguments: Boolean get() = this.valueParameters.count { !it.hasDefaultValue() } == 0 - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) private fun generateOverload(constructor: ClassConstructorDescriptor, parameters: List) { val overload = generateOverloadWithUniqueName(constructor, parameters) registerOverload(overload, constructor) } - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) private fun generateOverloadWithUniqueName( constructor: ClassConstructorDescriptor, parameters: List, @@ -97,7 +96,7 @@ class ConstructorsDefaultArgumentGeneratorDelegate( } if (parameters.isNotEmpty()) { - removeManglingOfOverload(overload, constructor, overload.valueParameters.last(), parameters.last()) + removeManglingOfOverload(overload.valueParameters.last(), parameters.last()) } return overload @@ -147,33 +146,31 @@ class ConstructorsDefaultArgumentGeneratorDelegate( private fun registerOverload(overloadDescriptor: ClassConstructorDescriptor, constructor: ClassConstructorDescriptor) { context.doInPhase(DefaultArgumentGenerator.RegisterOverloadsPhase) { - val overloadKirConstructor = kirProvider.getConstructor(overloadDescriptor) + val overloadKirConstructor = descriptorKirProvider.getConstructor(overloadDescriptor) - kirProvider.getConstructor(constructor).defaultArgumentsOverloads.add(overloadKirConstructor) + descriptorKirProvider.getConstructor(constructor).defaultArgumentsOverloads.add(overloadKirConstructor) } } private fun removeManglingOfOverload( - overloadDescriptor: ClassConstructorDescriptor, - constructor: ClassConstructorDescriptor, mangledValueParameterDescriptorFromOverload: ValueParameterDescriptor, mangledValueParameterDescriptorFromConstructor: ValueParameterDescriptor, ) { - context.doInPhase(DefaultArgumentGenerator.RemoveManglingOfOverloadsPhase) { - val overloadKirConstructor = kirProvider.getConstructor(overloadDescriptor) - val baseKirConstructor = kirProvider.getConstructor(constructor) + context.doInPhase(DefaultArgumentGenerator.RemoveManglingOfOverloadsInitPhase) { + val mangledValueParameterFromOverload = descriptorKirProvider.getValueParameter(mangledValueParameterDescriptorFromOverload) + val mangledValueParameterFromConstructor = descriptorKirProvider.getValueParameter(mangledValueParameterDescriptorFromConstructor) - val mangledValueParameterFromOverload = overloadKirConstructor.valueParameters - .single { it.kind.descriptorOrNull == mangledValueParameterDescriptorFromOverload } - .oirValueParameter - .originalSirValueParameter + doInPhase(DefaultArgumentGenerator.RemoveManglingOfOverloadsFinalizePhase) { + val sirMangledValueParameterFromOverload = mangledValueParameterFromOverload + .oirValueParameter + .originalSirValueParameter - val mangledValueParameterFromConstructor = baseKirConstructor.valueParameters - .single { it.kind.descriptorOrNull == mangledValueParameterDescriptorFromConstructor } - .oirValueParameter - .originalSirValueParameter + val sirMangledValueParameterFromConstructor = mangledValueParameterFromConstructor + .oirValueParameter + .originalSirValueParameter - mangledValueParameterFromOverload?.label = mangledValueParameterFromConstructor?.labelOrName + sirMangledValueParameterFromOverload?.label = sirMangledValueParameterFromConstructor?.labelOrName + } } } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/DefaultArgumentGeneratorDelegate.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/DefaultArgumentGeneratorDelegate.kt index dac7daa34..bfe571619 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/DefaultArgumentGeneratorDelegate.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/defaultarguments/delegate/DefaultArgumentGeneratorDelegate.kt @@ -1,9 +1,9 @@ package co.touchlab.skie.phases.features.defaultarguments.delegate -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.DescriptorModificationPhase interface DefaultArgumentGeneratorDelegate { - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) fun generate() } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/enums/EnumEntryRenamingPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/enums/EnumEntryRenamingPhase.kt index aa761f8a0..8260d9dfc 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/enums/EnumEntryRenamingPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/enums/EnumEntryRenamingPhase.kt @@ -3,12 +3,10 @@ package co.touchlab.skie.phases.features.enums import co.touchlab.skie.configuration.EnumInterop import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.kir.element.KirEnumEntry -import co.touchlab.skie.kir.util.hasArgumentValue +import co.touchlab.skie.phases.ScheduledPhase import co.touchlab.skie.phases.SirPhase -import co.touchlab.skie.phases.SkiePhase import co.touchlab.skie.sir.element.isExported import co.touchlab.skie.util.swift.toValidSwiftIdentifier -import org.jetbrains.kotlin.backend.konan.KonanFqNames object EnumEntryRenamingPhase : SirPhase { @@ -37,22 +35,20 @@ object EnumEntryRenamingPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - kirProvider.allEnums + kirProvider.kotlinEnums .filter { it.isSupported } .forEach { it.renameEnumEntries() } } - context(SkiePhase.Context) + context(ScheduledPhase.Context) private val KirClass.isSupported: Boolean get() = this.originalSirClass.isExported && !this.configuration[EnumInterop.LegacyCaseName] - context(SkiePhase.Context) + context(ScheduledPhase.Context) private val KirEnumEntry.isSupported: Boolean - get() = this.descriptor.annotations.findAnnotation(KonanFqNames.objCName) - ?.let { !it.hasArgumentValue("name") && !it.hasArgumentValue("swiftName") } - ?: true + get() = !this.hasUserDefinedName context(SirPhase.Context) private fun KirClass.renameEnumEntries() { @@ -68,9 +64,7 @@ object EnumEntryRenamingPhase : SirPhase { } private fun getNewEnumEntryName(enumEntry: KirEnumEntry): String { - val kotlinName = enumEntry.descriptor.name.asString() - - val words = NameParser(kotlinName).parse() + val words = NameParser(enumEntry.kotlinName).parse() val lowerCaseWords = words.map { it.lowercase() } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/enums/ExhaustiveEnumsGenerator.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/enums/ExhaustiveEnumsGenerator.kt index 79c7e97c6..55ace798b 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/enums/ExhaustiveEnumsGenerator.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/enums/ExhaustiveEnumsGenerator.kt @@ -4,7 +4,6 @@ import co.touchlab.skie.configuration.EnumInterop import co.touchlab.skie.configuration.SkieConfigurationFlag import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.phases.SirPhase -import co.touchlab.skie.phases.SkiePhase import co.touchlab.skie.phases.sir.type.hasStableNameTypeAlias import co.touchlab.skie.phases.util.MustBeExecutedAfterBridgingConfiguration import co.touchlab.skie.phases.util.StatefulSirPhase @@ -27,20 +26,20 @@ object ExhaustiveEnumsGenerator : SirPhase { context(SirPhase.Context) override suspend fun execute() { - kirProvider.allClasses + kirProvider.kotlinClasses .filter { it.isSupported } .forEach { generate(it) } } - context(SkiePhase.Context) + context(SirPhase.Context) private val KirClass.isSupported: Boolean get() = this.originalSirClass.isExported && this.kind == KirClass.Kind.Enum && this.isEnumInteropEnabled - context(SkiePhase.Context) + context(SirPhase.Context) private val KirClass.isEnumInteropEnabled: Boolean get() = this.configuration[EnumInterop.Enabled] diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/ConvertFlowsPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/ConvertFlowsPhase.kt index a2983f386..bb9fdf2c9 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/ConvertFlowsPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/ConvertFlowsPhase.kt @@ -7,31 +7,29 @@ import co.touchlab.skie.kir.element.KirFunction import co.touchlab.skie.kir.element.KirProperty import co.touchlab.skie.kir.element.KirSimpleFunction import co.touchlab.skie.kir.element.KirValueParameter -import co.touchlab.skie.kir.element.classDescriptorOrError import co.touchlab.skie.kir.type.BlockPointerKirType -import co.touchlab.skie.kir.type.ErrorOutKirType +import co.touchlab.skie.kir.type.DeclarationBackedKirType +import co.touchlab.skie.kir.type.DeclaredKirType import co.touchlab.skie.kir.type.KirType +import co.touchlab.skie.kir.type.NonNullReferenceKirType +import co.touchlab.skie.kir.type.NullableReferenceKirType import co.touchlab.skie.kir.type.OirBasedKirType -import co.touchlab.skie.kir.type.ReferenceKirType -import co.touchlab.skie.kir.type.SuspendCompletionKirType -import co.touchlab.skie.phases.SirPhase -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.KotlinTypeFactory -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.replaceArguments -import org.jetbrains.kotlin.types.isNullable -import org.jetbrains.kotlin.types.model.TypeArgumentMarker +import co.touchlab.skie.kir.type.PointerKirType +import co.touchlab.skie.kir.type.SpecialOirKirType +import co.touchlab.skie.kir.type.TypeParameterUsageKirType +import co.touchlab.skie.kir.type.UnresolvedFlowKirType +import co.touchlab.skie.phases.DescriptorConversionPhase class ConvertFlowsPhase( - context: SirPhase.Context, -) : SirPhase { + context: DescriptorConversionPhase.Context, +) : DescriptorConversionPhase { private val kirProvider = context.kirProvider + private val kirTypeTranslator = context.kirTypeTranslator - context(SirPhase.Context) + context(DescriptorConversionPhase.Context) override suspend fun execute() { - kirProvider.allClasses.forEach { + kirProvider.kotlinClasses.forEach { it.convertFlows() } } @@ -43,8 +41,10 @@ class ConvertFlowsPhase( } private fun KirClass.convertFlowsInSuperTypes() { - superTypes.replaceAll { - it.substituteFlows(configuration.flowMappingStrategy.limitedToTypeArguments()) + configuration.flowMappingStrategy.limitFlowMappingToTypeArguments().run { + superTypes.replaceAll { + it.substituteFlows() + } } } @@ -55,10 +55,12 @@ class ConvertFlowsPhase( } private fun KirCallableDeclaration<*>.convertFlows() { - when (this) { - is KirConstructor -> convertFlows() - is KirSimpleFunction -> convertFlows() - is KirProperty -> convertFlows() + configuration.flowMappingStrategy.run { + when (this@convertFlows) { + is KirConstructor -> convertFlows() + is KirSimpleFunction -> convertFlows() + is KirProperty -> convertFlows() + } } } @@ -66,14 +68,16 @@ class ConvertFlowsPhase( convertFlowsInValueParameters() } + context(FlowMappingStrategy) private fun KirSimpleFunction.convertFlows() { convertFlowsInValueParameters() - returnType = returnType.substituteFlows(configuration.flowMappingStrategy) + returnType = returnType.substituteFlows() } + context(FlowMappingStrategy) private fun KirProperty.convertFlows() { - type = type.substituteFlows(configuration.flowMappingStrategy) + type = type.substituteFlows() } private fun KirFunction<*>.convertFlowsInValueParameters() { @@ -83,57 +87,67 @@ class ConvertFlowsPhase( } private fun KirValueParameter.convertFlows() { - type = type.substituteFlows(configuration.flowMappingStrategy) + configuration.flowMappingStrategy.run { + type = type.substituteFlows() + } } - private fun KirType.substituteFlows(flowMappingStrategy: FlowMappingStrategy): KirType = + context(FlowMappingStrategy) + private fun KirType.substituteFlows(): KirType = when (this) { - is BlockPointerKirType -> copy(kotlinType = kotlinType.substituteFlows(flowMappingStrategy)) - ErrorOutKirType -> ErrorOutKirType + is NonNullReferenceKirType -> substituteFlows() + is NullableReferenceKirType -> copy(nonNullType = nonNullType.substituteFlows()) is OirBasedKirType -> this - is ReferenceKirType -> substituteFlows(flowMappingStrategy) - is SuspendCompletionKirType -> copy(kotlinType = kotlinType.substituteFlows(flowMappingStrategy)) + is PointerKirType -> copy(pointee = pointee.substituteFlows()) } - private fun ReferenceKirType.substituteFlows(flowMappingStrategy: FlowMappingStrategy): ReferenceKirType = - copy(kotlinType = kotlinType.substituteFlows(flowMappingStrategy)) - - private fun KotlinType.substituteFlows(flowMappingStrategy: FlowMappingStrategy): KotlinType { - val flowMappingStrategyForTypeArguments = flowMappingStrategy.forTypeArgumentsOf(this) - - return when (flowMappingStrategy) { - FlowMappingStrategy.Full -> { - val supportedFlow = SupportedFlow.from(this) + context(FlowMappingStrategy) + private fun NonNullReferenceKirType.substituteFlows(): NonNullReferenceKirType = + when (this) { + is BlockPointerKirType -> copy( + valueParameterTypes = valueParameterTypes.map { it.substituteFlows() }, + returnType = returnType.substituteFlows(), + ) + is DeclarationBackedKirType -> substituteFlows() + is SpecialOirKirType -> this + is TypeParameterUsageKirType -> this + } - supportedFlow?.createType(this, flowMappingStrategyForTypeArguments) - ?: this.withSubstitutedArgumentsForFlow(flowMappingStrategyForTypeArguments) + context(FlowMappingStrategy) + private fun DeclarationBackedKirType.substituteFlows(): DeclaredKirType = + when (this) { + is DeclaredKirType -> { + declaration.withFlowMappingForTypeArguments { + copy(typeArguments = typeArguments.map { it.substituteFlows() }) + } } - FlowMappingStrategy.TypeArgumentsOnly -> this.withSubstitutedArgumentsForFlow(flowMappingStrategyForTypeArguments) - FlowMappingStrategy.None -> this + is UnresolvedFlowKirType -> resolve() } - } - private fun SupportedFlow.createType(originalType: KotlinType, flowMappingStrategyForTypeArguments: FlowMappingStrategy): KotlinType { - val substitutedArguments = originalType.arguments.map { it.substituteFlows(flowMappingStrategyForTypeArguments) } + context(FlowMappingStrategy) + private fun UnresolvedFlowKirType.resolve(): DeclaredKirType = + when (this@FlowMappingStrategy) { + FlowMappingStrategy.Full -> toSkieFlowType() + FlowMappingStrategy.TypeArgumentsOnly, FlowMappingStrategy.None -> toCoroutinesFlowType() + } - val hasNullableTypeArgument = originalType.arguments.any { it.type.isNullable() } - val flowVariant = if (hasNullableTypeArgument) this.optionalVariant else this.requiredVariant - val substitute = flowVariant.getKotlinKirClass(kirProvider).classDescriptorOrError.defaultType + context(FlowMappingStrategy) + private fun UnresolvedFlowKirType.toSkieFlowType(): DeclaredKirType { + val kirClass = flowType.getKotlinKirClass(kirProvider) - return KotlinTypeFactory.simpleType(substitute, arguments = substitutedArguments).makeNullableAsSpecified(originalType.isNullable()) - } - - private fun KotlinType.withSubstitutedArgumentsForFlow(flowMappingStrategy: FlowMappingStrategy): KotlinType = - replaceArguments { it.substituteFlows(flowMappingStrategy) } as KotlinType + val typeArgument = kirClass.withFlowMappingForTypeArguments { + kirTypeTranslator.evaluateFlowTypeArgument().substituteFlows() + } - private fun TypeArgumentMarker.substituteFlows(flowMappingStrategy: FlowMappingStrategy): TypeProjection = - when (this) { - is TypeProjectionImpl -> { - val substitutedType = type.substituteFlows(flowMappingStrategy) + return DeclaredKirType( + declaration = kirClass, + typeArguments = listOf(typeArgument), + ) + } - if (this.type != substitutedType) TypeProjectionImpl(projectionKind, substitutedType) else this - } - is TypeProjection -> this - else -> error("Unsupported type argument $this.") - } + private fun UnresolvedFlowKirType.toCoroutinesFlowType(): DeclaredKirType = + DeclaredKirType( + declaration = flowType.getCoroutinesKirClass(kirProvider), + typeArguments = emptyList(), + ) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/FlowMappingStrategy.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/FlowMappingStrategy.kt index cc66e03cb..e8fa30e53 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/FlowMappingStrategy.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/FlowMappingStrategy.kt @@ -1,9 +1,9 @@ package co.touchlab.skie.phases.features.flow -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.supertypes +import co.touchlab.skie.kir.element.KirClass +import co.touchlab.skie.kir.type.DeclarationBackedKirType +import co.touchlab.skie.kir.type.DeclaredKirType +import co.touchlab.skie.kir.type.UnresolvedFlowKirType enum class FlowMappingStrategy { Full, TypeArgumentsOnly, None; @@ -14,18 +14,25 @@ enum class FlowMappingStrategy { "kotlin.collections.Map", ) - fun limitedToTypeArguments(): FlowMappingStrategy = + fun limitFlowMappingToTypeArguments(): FlowMappingStrategy = when (this) { Full, TypeArgumentsOnly -> TypeArgumentsOnly None -> None } - fun forTypeArgumentsOf(kotlinType: KotlinType): FlowMappingStrategy = - if (kotlinType.isIncompatibleWithSkieFlows) limitedToTypeArguments() else forTypeArgumentsOfCompatibleType() + inline fun KirClass.withFlowMappingForTypeArguments(action: FlowMappingStrategy.() -> T): T = + flowMappingForTypeArgumentsOf(this).action() - private val KotlinType.isIncompatibleWithSkieFlows: Boolean - get() = (listOf(this) + supertypes()).any { - (it.constructor.declarationDescriptor as? ClassDescriptor)?.fqNameSafe?.asString() in incompatibleTypeFqNames + fun flowMappingForTypeArgumentsOf(kirClass: KirClass): FlowMappingStrategy = + if (kirClass.isIncompatibleWithSkieFlows) limitFlowMappingToTypeArguments() else forTypeArgumentsOfCompatibleType() + + private val KirClass.isIncompatibleWithSkieFlows: Boolean + get() = kotlinFqName in incompatibleTypeFqNames || superTypes.any { it.isIncompatibleWithSkieFlows } + + private val DeclarationBackedKirType.isIncompatibleWithSkieFlows: Boolean + get() = when (this) { + is DeclaredKirType -> declaration.isIncompatibleWithSkieFlows + is UnresolvedFlowKirType -> true } private fun forTypeArgumentsOfCompatibleType(): FlowMappingStrategy = diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/SupportedFlow.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/SupportedFlow.kt index 6c20cd544..08b9e5101 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/SupportedFlow.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/SupportedFlow.kt @@ -34,6 +34,9 @@ enum class SupportedFlow(private val directParent: SupportedFlow?) { val kind: SupportedFlow + fun getCoroutinesKirClass(kirProvider: KirProvider): KirClass = + kind.getCoroutinesKirClass(kirProvider) + fun getKotlinKirClass(kirProvider: KirProvider): KirClass fun getSwiftClass(sirProvider: SirProvider): SirClass diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/UnifyFlowConfigurationForOverridesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/UnifyFlowConfigurationForOverridesPhase.kt index 631da6ae0..ea282f42d 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/UnifyFlowConfigurationForOverridesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/flow/UnifyFlowConfigurationForOverridesPhase.kt @@ -5,20 +5,20 @@ import co.touchlab.skie.kir.element.KirCallableDeclaration import co.touchlab.skie.kir.element.KirFunction import co.touchlab.skie.kir.element.KirOverridableDeclaration import co.touchlab.skie.kir.util.getEntireOverrideHierarchy -import co.touchlab.skie.phases.SirPhase +import co.touchlab.skie.phases.DescriptorConversionPhase class UnifyFlowConfigurationForOverridesPhase( - context: SirPhase.Context, -) : SirPhase { + context: DescriptorConversionPhase.Context, +) : DescriptorConversionPhase { private val kirProvider = context.kirProvider - context(SirPhase.Context) + context(DescriptorConversionPhase.Context) override fun isActive(): Boolean = SkieConfigurationFlag.Feature_CoroutinesInterop.isEnabled - context(SirPhase.Context) + context(DescriptorConversionPhase.Context) override suspend fun execute() { - kirProvider.allOverridableDeclaration + kirProvider.kotlinOverridableDeclaration .filter { it.overriddenDeclarations.isEmpty() && it.overriddenBy.isNotEmpty() } .forEach { it.unifyConfigurationForOverrides() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConversionParentProvider.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConversionParentProvider.kt index 9f2c3aa73..416aca552 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConversionParentProvider.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConversionParentProvider.kt @@ -24,8 +24,8 @@ class FileScopeConversionParentProvider( private val context: SirPhase.Context, ) { + private val kirBuiltins = context.kirBuiltins private val sirProvider = context.sirProvider - private val oirBuiltins = context.oirBuiltins private val sirBuiltins = context.sirBuiltins private val cache: MutableMap> = mutableMapOf() @@ -89,7 +89,7 @@ class FileScopeConversionParentProvider( is SpecialSirType.Any -> { createNonOptionalExtension( file = namespace, - sirClass = oirBuiltins.NSObject.originalSirClass, + sirClass = kirBuiltins.NSObject.originalSirClass, ).let(::listOfNotNull) } is NullableSirType -> getOptionalExtensions(callableDeclaration, type, namespace) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConvertor.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConvertor.kt index 3c4d3e97c..cd6bbe118 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConvertor.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConvertor.kt @@ -19,7 +19,7 @@ class FileScopeConvertor( context(SirPhase.Context) override suspend fun execute() { - kirProvider.allClasses + kirProvider.kotlinClasses .filter { it.kind == KirClass.Kind.File } .flatMap { it.callableDeclarations } .filter { it.isInteropEnabled } @@ -53,7 +53,7 @@ class FileScopeConvertor( is KirSimpleFunction.Kind.PropertyGetter -> interfaceExtensionMembersDelegate.generateInterfaceExtensionPropertyWrapper(function) is KirSimpleFunction.Kind.PropertySetter -> { // Property wrapper must be generated only once - if (function.kind.propertyDescriptor.getter == null) { + if (function.kind.associatedGetter == null) { interfaceExtensionMembersDelegate.generateInterfaceExtensionPropertyWrapper(function) } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConvertorDelegateScope.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConvertorDelegateScope.kt index 829c684a7..9e7db41ae 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConvertorDelegateScope.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/FileScopeConvertorDelegateScope.kt @@ -1,8 +1,6 @@ package co.touchlab.skie.phases.features.functions import co.touchlab.skie.kir.element.KirBridgeableDeclaration -import co.touchlab.skie.kir.element.KirClass -import co.touchlab.skie.kir.element.KirSimpleFunction import co.touchlab.skie.sir.element.SirCallableDeclaration import co.touchlab.skie.sir.element.receiverDeclaration import io.outfoxx.swiftpoet.TypeName @@ -22,9 +20,6 @@ interface FileScopeConvertorDelegateScope { } } - fun KirClass.findFunctionWithKind(kind: KirSimpleFunction.Kind): KirSimpleFunction? = - callableDeclarations.filterIsInstance().firstOrNull { it.kind == kind } - val SirCallableDeclaration.kotlinStaticMemberOwnerTypeName: TypeName get() { val owner = receiverDeclaration ?: error("Callable declarations from Kotlin should always have an owner. Was: $this") diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/InterfaceExtensionMembersConvertorDelegate.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/InterfaceExtensionMembersConvertorDelegate.kt index c12ccdedc..f1c560d9f 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/InterfaceExtensionMembersConvertorDelegate.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/functions/InterfaceExtensionMembersConvertorDelegate.kt @@ -50,12 +50,8 @@ class InterfaceExtensionMembersConvertorDelegate( fun generateInterfaceExtensionPropertyWrapper(function: KirSimpleFunction) { val (kirGetter, kirSetter) = when (val kind = function.kind) { - is KirSimpleFunction.Kind.PropertyGetter -> { - function to function.owner.findFunctionWithKind(KirSimpleFunction.Kind.PropertySetter(kind.propertyDescriptor)) - } - is KirSimpleFunction.Kind.PropertySetter -> { - function.owner.findFunctionWithKind(KirSimpleFunction.Kind.PropertyGetter(kind.propertyDescriptor)) to function - } + is KirSimpleFunction.Kind.PropertyGetter -> function to kind.associatedSetter + is KirSimpleFunction.Kind.PropertySetter -> kind.associatedGetter to function KirSimpleFunction.Kind.Function -> error("Function is not a converted property. Was: $function") } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/sealed/SealedGeneratorExtensionContainer.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/sealed/SealedGeneratorExtensionContainer.kt index 1e6053278..600cd592b 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/sealed/SealedGeneratorExtensionContainer.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/sealed/SealedGeneratorExtensionContainer.kt @@ -2,7 +2,6 @@ package co.touchlab.skie.phases.features.sealed import co.touchlab.skie.configuration.SealedInterop import co.touchlab.skie.kir.element.KirClass -import co.touchlab.skie.kir.element.classDescriptorOrError import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.sir.element.SirClass import co.touchlab.skie.sir.element.superClassType @@ -33,7 +32,7 @@ interface SealedGeneratorExtensionContainer { get() { val configuredName = this.configuration[SealedInterop.Case.Name] - return configuredName ?: classDescriptorOrError.name.identifier.replaceFirstChar { it.lowercase() }.toValidSwiftIdentifier() + return configuredName ?: kotlinIdentifier.replaceFirstChar { it.lowercase() }.toValidSwiftIdentifier() } val KirClass.enumCaseNameBasedOnSwiftIdentifier: String diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/sealed/SealedInteropGenerator.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/sealed/SealedInteropGenerator.kt index d764ae2f1..05877f7ba 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/sealed/SealedInteropGenerator.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/sealed/SealedInteropGenerator.kt @@ -16,7 +16,7 @@ class SealedInteropGenerator( context(SirPhase.Context) override suspend fun execute() { - kirProvider.allClasses + kirProvider.kotlinClasses .filter { it.isSupported } .forEach { generate(it) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/KotlinSuspendGeneratorDelegate.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/KotlinSuspendGeneratorDelegate.kt index 1f4b7d2ae..82e586675 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/KotlinSuspendGeneratorDelegate.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/KotlinSuspendGeneratorDelegate.kt @@ -7,8 +7,8 @@ import co.touchlab.skie.kir.irbuilder.createFunction import co.touchlab.skie.kir.irbuilder.util.copyIndexing import co.touchlab.skie.kir.irbuilder.util.copyWithoutDefaultValue import co.touchlab.skie.kir.irbuilder.util.createValueParameter +import co.touchlab.skie.phases.DescriptorConversionPhase import co.touchlab.skie.phases.DescriptorModificationPhase -import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.phases.features.suspend.kotlin.SuspendKotlinBridgeBodyGenerator import co.touchlab.skie.phases.util.doInPhase import co.touchlab.skie.sir.element.SirVisibility @@ -61,9 +61,13 @@ class KotlinSuspendGeneratorDelegate( } private fun FunctionDescriptor.hide() { - context.doInPhase(SuspendGenerator.KotlinBridgingFunctionVisibilityConfigurationPhase) { - kirProvider.getFunction(this@hide).originalSirFunction.applyToEntireOverrideHierarchy { - visibility = SirVisibility.Internal + context.doInPhase(SuspendGenerator.KotlinBridgingFunctionVisibilityConfigurationInitPhase) { + val kirFunction = descriptorKirProvider.getFunction(this@hide) + + doInPhase(SuspendGenerator.KotlinBridgingFunctionVisibilityConfigurationFinalizePhase) { + kirFunction.originalSirFunction.applyToEntireOverrideHierarchy { + visibility = SirVisibility.Internal + } } } } @@ -76,6 +80,7 @@ class KotlinSuspendGeneratorDelegate( namespace = context.declarationBuilder.getCustomNamespace("__SkieSuspendWrappers"), annotations = Annotations.EMPTY, ) { + // WIP Replace with typeConstructor.parameters fun DeclarationDescriptor.typeParametersInScope(): List { return when (this) { is ClassifierDescriptorWithTypeParameters -> { @@ -138,23 +143,20 @@ class KotlinSuspendGeneratorDelegate( ) context.doInPhase(SuspendGenerator.FlowMappingConfigurationPhase) { - configureFlowMappingForReceiver(bridgingFunctionDescriptor, dispatchReceiverParameter) + configureFlowMappingForReceiver(dispatchReceiverParameter) } this.add(dispatchReceiverParameter) } } - context(SirPhase.Context) + context(DescriptorConversionPhase.Context) private fun configureFlowMappingForReceiver( - bridgingFunctionDescriptor: FunctionDescriptor, dispatchReceiverParameter: ValueParameterDescriptor, ) { - val configuration = kirProvider.getFunction(bridgingFunctionDescriptor).valueParameters - .single { it.descriptorOrNull == dispatchReceiverParameter } - .configuration + val kirValueParameter = descriptorKirProvider.getValueParameter(dispatchReceiverParameter) - configuration.flowMappingStrategy = configuration.flowMappingStrategy.limitedToTypeArguments() + kirValueParameter.configuration.flowMappingStrategy = kirValueParameter.configuration.flowMappingStrategy.limitFlowMappingToTypeArguments() } private fun MutableList.addExtensionReceiver( @@ -170,7 +172,7 @@ class KotlinSuspendGeneratorDelegate( type = typeSubstitutor.safeSubstitute(extensionReceiver.type, Variance.INVARIANT), ) - configureFlowMappingForExtensionReceiver(originalFunctionDescriptor, bridgingFunctionDescriptor, extensionReceiverParameter) + configureFlowMappingForExtensionReceiver(originalFunctionDescriptor, extensionReceiverParameter) this.add(extensionReceiverParameter) } @@ -178,17 +180,16 @@ class KotlinSuspendGeneratorDelegate( private fun configureFlowMappingForExtensionReceiver( originalFunctionDescriptor: FunctionDescriptor, - bridgingFunctionDescriptor: FunctionDescriptor, extensionReceiverParameter: ValueParameterDescriptor, ) { context.doInPhase(SuspendGenerator.FlowMappingConfigurationPhase) { - val function = kirProvider.getFunction(originalFunctionDescriptor) + val function = descriptorKirProvider.getFunction(originalFunctionDescriptor) val isExtensionReceiverUsedAsSwiftReceiver = function.scope == KirScope.Member && originalFunctionDescriptor.dispatchReceiverParameter == null if (isExtensionReceiverUsedAsSwiftReceiver) { - configureFlowMappingForReceiver(bridgingFunctionDescriptor, extensionReceiverParameter) + configureFlowMappingForReceiver(extensionReceiverParameter) } } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/SuspendGenerator.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/SuspendGenerator.kt index 7da015f1b..6bac39c1c 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/SuspendGenerator.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/SuspendGenerator.kt @@ -1,14 +1,12 @@ package co.touchlab.skie.phases.features.suspend -import co.touchlab.skie.configuration.SimpleFunctionConfiguration import co.touchlab.skie.configuration.SkieConfigurationFlag -import co.touchlab.skie.configuration.SuspendInterop import co.touchlab.skie.configuration.isSuspendInteropEnabled import co.touchlab.skie.configuration.provider.descriptor.configuration import co.touchlab.skie.kir.descriptor.DescriptorProvider import co.touchlab.skie.kir.descriptor.allExposedMembers import co.touchlab.skie.phases.DescriptorModificationPhase -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.util.StatefulDescriptorConversionPhase import co.touchlab.skie.phases.util.StatefulSirPhase import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor @@ -29,7 +27,7 @@ object SuspendGenerator : DescriptorModificationPhase { } } - context(SkiePhase.Context) + context(DescriptorModificationPhase.Context) private val DescriptorProvider.allSupportedFunctions: List get() = this.allExposedMembers.filterIsInstance() .filter { mapper.isBaseMethod(it) } @@ -39,9 +37,13 @@ object SuspendGenerator : DescriptorModificationPhase { private val SimpleFunctionDescriptor.isSupported: Boolean get() = this.isSuspend - object FlowMappingConfigurationPhase : StatefulSirPhase() + object FlowMappingConfigurationPhase : StatefulDescriptorConversionPhase() + + object KotlinBridgingFunctionVisibilityConfigurationInitPhase : StatefulDescriptorConversionPhase() + + object KotlinBridgingFunctionVisibilityConfigurationFinalizePhase : StatefulSirPhase() - object KotlinBridgingFunctionVisibilityConfigurationPhase : StatefulSirPhase() + object SwiftBridgeGeneratorInitPhase : StatefulDescriptorConversionPhase() - object SwiftBridgeGeneratorPhase : StatefulSirPhase() + object SwiftBridgeGeneratorFinalizePhase : StatefulSirPhase() } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/SwiftSuspendGeneratorDelegate.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/SwiftSuspendGeneratorDelegate.kt index e5809fd50..af02a04eb 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/SwiftSuspendGeneratorDelegate.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/features/suspend/SwiftSuspendGeneratorDelegate.kt @@ -35,20 +35,25 @@ class SwiftSuspendGeneratorDelegate( originalFunctionDescriptor: FunctionDescriptor, kotlinBridgingFunctionDescriptor: FunctionDescriptor, ) { - context.doInPhase(SuspendGenerator.SwiftBridgeGeneratorPhase) { - val bridgeModel = BridgeModel( - suspendKirFunction = kirProvider.getFunction(originalFunctionDescriptor), - kotlinBridgingKirFunction = kirProvider.getFunction(kotlinBridgingFunctionDescriptor), - ) + context.doInPhase(SuspendGenerator.SwiftBridgeGeneratorInitPhase) { + val suspendKirFunction = descriptorKirProvider.getFunction(originalFunctionDescriptor) + val kotlinBridgingKirFunction = descriptorKirProvider.getFunction(kotlinBridgingFunctionDescriptor) - val extension = sirProvider.getExtension( - classDeclaration = bridgeModel.extensionTypeDeclarationForBridgingFunction, - parent = classNamespaceProvider.getNamespaceFile(bridgeModel.suspendFunctionOwner), - ) + doInPhase(SuspendGenerator.SwiftBridgeGeneratorFinalizePhase) { + val bridgeModel = BridgeModel( + suspendKirFunction = suspendKirFunction, + kotlinBridgingKirFunction = kotlinBridgingKirFunction, + ) - bridgeModel.suspendKirFunction.bridgedSirFunction = extension.createSwiftBridgingFunction(bridgeModel) + val extension = sirProvider.getExtension( + classDeclaration = bridgeModel.extensionTypeDeclarationForBridgingFunction, + parent = classNamespaceProvider.getNamespaceFile(bridgeModel.suspendFunctionOwner), + ) - hideOriginalFunction(bridgeModel) + bridgeModel.suspendKirFunction.bridgedSirFunction = extension.createSwiftBridgingFunction(bridgeModel) + + hideOriginalFunction(bridgeModel) + } } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/header/GenerateFakeObjCDependenciesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/header/GenerateFakeObjCDependenciesPhase.kt index d42c358d1..561a75cd0 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/header/GenerateFakeObjCDependenciesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/header/GenerateFakeObjCDependenciesPhase.kt @@ -10,7 +10,7 @@ object GenerateFakeObjCDependenciesPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - oirProvider.allExternalClassesAndProtocols + oirProvider.externalClassesAndProtocols .groupBy { it.originalSirClass.module } .filterKeys { it is SirModule.External && it.name != "Foundation" } .mapKeys { it.key as SirModule.External } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateExposedKirTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateExposedKirTypesPhase.kt new file mode 100644 index 000000000..5896d827b --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateExposedKirTypesPhase.kt @@ -0,0 +1,240 @@ +package co.touchlab.skie.phases.kir + +import co.touchlab.skie.configuration.ClassConfiguration +import co.touchlab.skie.configuration.FileConfiguration +import co.touchlab.skie.configuration.FileOrClassConfiguration +import co.touchlab.skie.configuration.ModuleConfiguration +import co.touchlab.skie.configuration.PackageConfiguration +import co.touchlab.skie.kir.descriptor.DescriptorKirProvider +import co.touchlab.skie.kir.element.KirClass +import co.touchlab.skie.kir.element.KirEnumEntry +import co.touchlab.skie.kir.element.KirTypeParameter +import co.touchlab.skie.kir.element.superClass +import co.touchlab.skie.kir.type.DeclarationBackedKirType +import co.touchlab.skie.kir.type.translation.withTypeParameterScope +import co.touchlab.skie.kir.util.hasArgumentValue +import co.touchlab.skie.oir.element.OirTypeParameter +import co.touchlab.skie.phases.DescriptorConversionPhase +import org.jetbrains.kotlin.backend.konan.KonanFqNames +import org.jetbrains.kotlin.backend.konan.descriptors.enumEntries +import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.SourceFile +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.isSealed +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.types.Variance + +class CreateExposedKirTypesPhase( + context: DescriptorConversionPhase.Context, +) : DescriptorConversionPhase { + + private val descriptorProvider = context.descriptorProvider + private val kirProvider = context.kirProvider + private val descriptorKirProvider = context.descriptorKirProvider + private val kirBuiltins = context.kirBuiltins + private val namer = context.namer + private val descriptorConfigurationProvider = context.descriptorConfigurationProvider + private val rootConfiguration = context.rootConfiguration + private val kirTypeTranslator = context.kirTypeTranslator + + private val descriptorsToClasses = mutableMapOf() + + private val sourceFileConfiguration = ClassConfiguration( + FileOrClassConfiguration.File( + FileConfiguration(PackageConfiguration(ModuleConfiguration(rootConfiguration))), + ), + ) + + context(DescriptorConversionPhase.Context) + override suspend fun execute() { + createRegularClasses() + createFileClasses() + configureSealedSubclasses() + + configureSuperTypes() + + kirProvider.initializeKotlinClassCache() + } + + private fun createRegularClasses() { + descriptorProvider.exposedClasses.forEach(::getOrCreateClass) + } + + private fun createFileClasses() { + descriptorProvider.exposedFiles.forEach(::createClass) + } + + private fun getOrCreateClass(descriptor: ClassDescriptor): KirClass = + descriptorsToClasses.getOrPut(descriptor) { + createClass(descriptor) + } + + private fun createClass(descriptor: ClassDescriptor): KirClass { + val parent = (descriptor.containingDeclaration as? ClassDescriptor) + ?.takeIf { it in descriptorProvider.exposedClasses } + ?.let { getOrCreateClass(it) } + ?: descriptorKirProvider.getKotlinModule(descriptor.module) + + val classOrProtocolName = namer.getClassOrProtocolName(descriptor) + + val kirClass = KirClass( + kotlinFqName = descriptor.fqNameSafe.asString(), + objCName = classOrProtocolName.objCName, + swiftName = classOrProtocolName.swiftName, + parent = parent, + kind = when (descriptor.kind) { + ClassKind.CLASS -> KirClass.Kind.Class + ClassKind.INTERFACE -> KirClass.Kind.Interface + ClassKind.ENUM_CLASS -> KirClass.Kind.Enum + ClassKind.OBJECT -> if (descriptor.isCompanionObject) KirClass.Kind.CompanionObject else KirClass.Kind.Object + ClassKind.ENUM_ENTRY, ClassKind.ANNOTATION_CLASS -> error("Unexpected class kind: ${descriptor.kind}") + }, + origin = KirClass.Origin.Kotlin, + superTypes = emptyList(), + isSealed = descriptor.isSealed(), + hasUnexposedSealedSubclasses = descriptor.sealedSubclasses.any { !it.isExposed }, + configuration = descriptorConfigurationProvider.getConfiguration(descriptor), + ) + + descriptorKirProvider.registerClass(kirClass, descriptor) + + configureClassParent(kirClass) + + with(descriptorKirProvider) { + createTypeParameters(kirClass, descriptor, namer) + } + + createEnumEntries(kirClass, descriptor) + + return kirClass + } + + private fun createEnumEntries(kirClass: KirClass, descriptor: ClassDescriptor) { + if (kirClass.kind != KirClass.Kind.Enum) { + return + } + + descriptor.enumEntries.forEachIndexed { index, classDescriptor -> + val originalDescriptor = classDescriptor.original + + val enumEntry = KirEnumEntry( + kotlinName = classDescriptor.name.asString(), + objCSelector = namer.getEnumEntrySelector(originalDescriptor), + swiftName = namer.getEnumEntrySwiftName(originalDescriptor), + owner = kirClass, + index = index, + hasUserDefinedName = classDescriptor.hasUserDefinedName, + ) + + descriptorKirProvider.registerEnumEntry(enumEntry, classDescriptor) + } + } + + private fun configureClassParent(kirClass: KirClass) { + if (kirClass.parent is KirClass) { + if (kirClass.kind == KirClass.Kind.CompanionObject) { + kirClass.parent.companionObject = kirClass + } + } + } + + private fun createClass(file: SourceFile) { + val module = descriptorKirProvider.getKotlinModule(descriptorProvider.getFileModule(file)) + + val fileClassName = namer.getFileClassName(file) + + val kirClass = KirClass( + kotlinFqName = fileClassName.swiftName, + objCName = fileClassName.objCName, + swiftName = fileClassName.swiftName, + parent = module, + kind = KirClass.Kind.File, + origin = KirClass.Origin.Kotlin, + superTypes = listOf(kirBuiltins.Base.defaultType), + isSealed = false, + hasUnexposedSealedSubclasses = false, + configuration = sourceFileConfiguration, + ) + + descriptorKirProvider.registerFile(kirClass, file) + } + + private fun configureSealedSubclasses() { + descriptorsToClasses.forEach { + configureSealedSubclasses(it.value, it.key) + } + } + + private fun configureSealedSubclasses(kirClass: KirClass, classDescriptor: ClassDescriptor) { + kirClass.sealedSubclasses.addAll( + classDescriptor.sealedSubclasses.mapNotNull { descriptorsToClasses[it] }, + ) + } + + private fun configureSuperTypes() { + descriptorsToClasses.forEach { + configureSuperTypes(it.value, it.key) + } + } + + private fun configureSuperTypes(kirClass: KirClass, classDescriptor: ClassDescriptor) { + kirClass.withTypeParameterScope { + val superTypesWithoutAny = classDescriptor.defaultType.constructor.supertypes + .filter { !KotlinBuiltIns.isAnyOrNullableAny(it) } + .map { kirTypeTranslator.mapReferenceType(it) } + .filterIsInstance() + + kirClass.superTypes.addAll(superTypesWithoutAny) + + if (kirClass.kind != KirClass.Kind.Interface && kirClass.superClass == null) { + kirClass.superTypes.add(kirBuiltins.Base.defaultType) + } + } + } + + private val ClassDescriptor.isExposed: Boolean + get() = this in descriptorProvider.exposedClasses + + private val ClassDescriptor.hasUserDefinedName: Boolean + get() = this.annotations.findAnnotation(KonanFqNames.objCName) + ?.let { !it.hasArgumentValue("name") && !it.hasArgumentValue("swiftName") } + ?: true + + companion object { + + context(DescriptorKirProvider) + fun createTypeParameters(kirClass: KirClass, descriptor: ClassDescriptor, namer: ObjCExportNamer) { + if (kirClass.kind != KirClass.Kind.Class) { + return + } + + descriptor.typeConstructor.parameters.forEach { typeParameter -> + createTypeParameter(kirClass, typeParameter, namer) + } + } + + context(DescriptorKirProvider) + private fun createTypeParameter( + kirClass: KirClass, + typeParameterDescriptor: TypeParameterDescriptor, + namer: ObjCExportNamer, + ) { + val typeParameter = KirTypeParameter( + name = namer.getTypeParameterName(typeParameterDescriptor), + parent = kirClass, + variance = when (typeParameterDescriptor.variance) { + Variance.INVARIANT -> OirTypeParameter.Variance.Invariant + Variance.IN_VARIANCE -> OirTypeParameter.Variance.Contravariant + Variance.OUT_VARIANCE -> OirTypeParameter.Variance.Covariant + }, + // Bounds are not supported. + ) + + this@DescriptorKirProvider.registerTypeParameter(typeParameter, typeParameterDescriptor) + } + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateKirMembersPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateKirMembersPhase.kt index 20cbbc9a9..c2daf3918 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateKirMembersPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateKirMembersPhase.kt @@ -13,13 +13,18 @@ import co.touchlab.skie.kir.element.KirProperty import co.touchlab.skie.kir.element.KirScope import co.touchlab.skie.kir.element.KirSimpleFunction import co.touchlab.skie.kir.element.KirValueParameter +import co.touchlab.skie.kir.type.translation.KirTypeParameterScope +import co.touchlab.skie.kir.type.translation.withTypeParameterScope import co.touchlab.skie.kir.util.addOverrides import co.touchlab.skie.oir.element.OirFunction -import co.touchlab.skie.phases.SirPhase +import co.touchlab.skie.phases.DescriptorConversionPhase +import co.touchlab.skie.phases.oir.util.getOirValueParameterName +import co.touchlab.skie.util.swift.toValidSwiftIdentifier import org.jetbrains.kotlin.backend.konan.KonanFqNames import org.jetbrains.kotlin.backend.konan.objcexport.MethodBridge import org.jetbrains.kotlin.backend.konan.objcexport.MethodBridgeValueParameter import org.jetbrains.kotlin.backend.konan.objcexport.valueParametersAssociated +import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor @@ -34,31 +39,42 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.SourceFile import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass +import org.jetbrains.kotlin.resolve.isValueClass class CreateKirMembersPhase( - context: SirPhase.Context, -) : SirPhase { + context: DescriptorConversionPhase.Context, +) : DescriptorConversionPhase { private val descriptorProvider = context.descriptorProvider + private val descriptorKirProvider = context.descriptorKirProvider private val kirProvider = context.kirProvider private val mapper = context.mapper - private val kirTypeTranslator = context.kirTypeTranslator private val descriptorConfigurationProvider = context.descriptorConfigurationProvider + private val namer = context.namer + private val kirDeclarationTypeTranslator = context.kirDeclarationTypeTranslator private val functionCache = mutableMapOf() private val propertyCache = mutableMapOf() - context(SirPhase.Context) + private val convertedPropertyKindLazyInitializers = mutableListOf<() -> Unit>() + + context(DescriptorConversionPhase.Context) override suspend fun execute() { - kirProvider.allClasses.forEach(::createMembers) + kirProvider.kotlinClasses.forEach(::createMembers) kirProvider.initializeCallableDeclarationsCache() + + initializeConvertedPropertyKinds() + } + + private fun initializeConvertedPropertyKinds() { + convertedPropertyKindLazyInitializers.forEach { it() } } private fun createMembers(kirClass: KirClass) { - when (kirClass.descriptor) { - is KirClass.Descriptor.Class -> createMembers(kirClass.descriptor.value, kirClass) - is KirClass.Descriptor.File -> createMembers(kirClass.descriptor.value, kirClass) + when (kirClass.kind) { + KirClass.Kind.File -> createMembers(descriptorKirProvider.getClassSourceFile(kirClass), kirClass) + else -> createMembers(descriptorKirProvider.getClassDescriptor(kirClass), kirClass) } } @@ -90,14 +106,21 @@ class CreateKirMembersPhase( val methodBridge = mapper.bridgeMethod(originalDescriptor) val constructor = KirConstructor( - descriptor = originalDescriptor, + kotlinName = descriptor.name.asString(), + kotlinSignature = descriptor.signature, + objCSelector = namer.getSelector(descriptor), + swiftName = namer.getSwiftName(descriptor), owner = kirClass, errorHandlingStrategy = methodBridge.returnBridge.errorHandlingStrategy, deprecationLevel = descriptor.kirDeprecationLevel, - configuration = descriptorConfigurationProvider.getConfiguration(originalDescriptor), + configuration = descriptorConfigurationProvider.getConfiguration(descriptor), ) - createValueParameters(constructor, originalDescriptor, methodBridge) + descriptorKirProvider.registerCallableDeclaration(constructor, descriptor) + + kirClass.withTypeParameterScope { + createValueParameters(constructor, originalDescriptor, methodBridge) + } } private fun createMember(descriptor: CallableMemberDescriptor, kirClass: KirClass, origin: Origin) { @@ -128,7 +151,7 @@ class CreateKirMembersPhase( val classDescriptor = descriptorProvider.getReceiverClassDescriptorOrNull(descriptor) ?: error("Unsupported function $descriptor") - val kirClass = kirProvider.getClass(classDescriptor) + val kirClass = descriptorKirProvider.getClass(classDescriptor) return getOrCreateFunction(descriptor, kirClass, origin) } @@ -143,34 +166,66 @@ class CreateKirMembersPhase( val methodBridge = mapper.bridgeMethod(baseDescriptor) - val function = KirSimpleFunction( - baseDescriptor = baseDescriptor, - descriptor = originalDescriptor, - owner = kirClass, - origin = origin, - isSuspend = descriptor.isSuspend, - returnType = kirTypeTranslator.mapReturnType(originalDescriptor, methodBridge.returnBridge), - kind = when (descriptor) { - is SimpleFunctionDescriptor -> KirSimpleFunction.Kind.Function - is PropertyGetterDescriptor -> KirSimpleFunction.Kind.PropertyGetter(descriptor.correspondingProperty.original) - is PropertySetterDescriptor -> KirSimpleFunction.Kind.PropertySetter(descriptor.correspondingProperty.original) - else -> error("Unsupported function type: $descriptor") - }, - scope = kirClass.callableDeclarationScope, - errorHandlingStrategy = methodBridge.returnBridge.errorHandlingStrategy, - deprecationLevel = descriptor.kirDeprecationLevel, - isRefinedInSwift = baseDescriptor.isRefinedInSwift, - configuration = getFunctionConfiguration(descriptor), - ) + kirClass.withTypeParameterScope { + val function = KirSimpleFunction( + kotlinName = descriptor.name.asString(), + kotlinSignature = descriptor.signature, + objCSelector = namer.getSelector(baseDescriptor), + swiftName = namer.getSwiftName(baseDescriptor), + owner = kirClass, + origin = origin, + isSuspend = descriptor.isSuspend, + kind = descriptor.getKind(kirClass, origin), + returnType = kirDeclarationTypeTranslator.mapReturnType( + originalDescriptor, + methodBridge.returnBridge, + ), + scope = kirClass.callableDeclarationScope, + errorHandlingStrategy = methodBridge.returnBridge.errorHandlingStrategy, + deprecationLevel = descriptor.kirDeprecationLevel, + isRefinedInSwift = baseDescriptor.isRefinedInSwift, + configuration = getFunctionConfiguration(descriptor), + ) + + descriptorKirProvider.registerCallableDeclaration(function, descriptor) + + getDirectParents(descriptor) + .map { getOrCreateOverriddenFunction(it, origin) } + .let { function.addOverrides(it) } + + createValueParameters(function, descriptor, methodBridge) + + return function + } + } - getDirectParents(descriptor) - .map { getOrCreateOverriddenFunction(it, origin) } - .let { function.addOverrides(it) } + private fun FunctionDescriptor.getKind(kirClass: KirClass, origin: Origin): KirSimpleFunction.Kind = + when (this) { + is SimpleFunctionDescriptor -> KirSimpleFunction.Kind.Function + is PropertyGetterDescriptor -> { + val kind = KirSimpleFunction.Kind.PropertyGetter(null) - createValueParameters(function, descriptor, methodBridge) + this.correspondingProperty.setter?.let { + convertedPropertyKindLazyInitializers.add { + kind.associatedSetter = getOrCreateFunction(it, kirClass, origin) + } + } - return function - } + kind + } + is PropertySetterDescriptor -> { + val kind = KirSimpleFunction.Kind.PropertySetter(null) + + this.correspondingProperty.getter?.let { + convertedPropertyKindLazyInitializers.add { + kind.associatedGetter = getOrCreateFunction(it, kirClass, origin) + } + } + + kind + } + else -> error("Unsupported function type: $this") + } private fun getFunctionConfiguration(descriptor: FunctionDescriptor): SimpleFunctionConfiguration = when (descriptor) { @@ -200,7 +255,7 @@ class CreateKirMembersPhase( val classDescriptor = descriptorProvider.getReceiverClassDescriptorOrNull(descriptor) ?: error("Unsupported property $descriptor") - val kirClass = kirProvider.getClass(classDescriptor) + val kirClass = descriptorKirProvider.getClass(classDescriptor) return getOrCreateProperty(descriptor, kirClass, origin) } @@ -215,26 +270,35 @@ class CreateKirMembersPhase( val getterBridge = mapper.bridgeMethod(baseDescriptor.getter!!) - val property = KirProperty( - baseDescriptor = baseDescriptor, - descriptor = originalDescriptor, - owner = kirClass, - origin = origin, - scope = kirClass.callableDeclarationScope, - type = kirTypeTranslator.mapReturnType(originalDescriptor.getter!!, getterBridge.returnBridge), - isVar = descriptor.setter?.let { mapper.shouldBeExposed(it) } ?: false, - deprecationLevel = descriptor.kirDeprecationLevel, - isRefinedInSwift = baseDescriptor.isRefinedInSwift, - configuration = descriptorConfigurationProvider.getConfiguration(originalDescriptor), - ) - - getDirectParents(descriptor) - .map { getOrCreateOverriddenProperty(it, origin) } - .let { property.addOverrides(it) } - - return property + val propertyName = namer.getPropertyName(baseDescriptor) + + kirClass.withTypeParameterScope { + val property = KirProperty( + kotlinName = descriptor.name.asString(), + kotlinSignature = descriptor.signature, + objCName = propertyName.objCName, + swiftName = propertyName.swiftName, + owner = kirClass, + origin = origin, + scope = kirClass.callableDeclarationScope, + type = kirDeclarationTypeTranslator.mapReturnType(originalDescriptor.getter!!, getterBridge.returnBridge), + isVar = descriptor.setter?.let { mapper.shouldBeExposed(it) } ?: false, + deprecationLevel = descriptor.kirDeprecationLevel, + isRefinedInSwift = baseDescriptor.isRefinedInSwift, + configuration = descriptorConfigurationProvider.getConfiguration(originalDescriptor), + ) + + descriptorKirProvider.registerCallableDeclaration(property, descriptor) + + getDirectParents(descriptor) + .map { getOrCreateOverriddenProperty(it, origin) } + .let { property.addOverrides(it) } + + return property + } } + context(KirTypeParameterScope) private fun createValueParameters( function: KirFunction<*>, descriptor: FunctionDescriptor, @@ -242,22 +306,52 @@ class CreateKirMembersPhase( ) { methodBridge.valueParametersAssociated(descriptor) .forEach { (parameterBridge, parameterDescriptor) -> - KirValueParameter( - parent = function, - type = kirTypeTranslator.mapValueParameterType(descriptor, parameterDescriptor, parameterBridge), - kind = when (parameterBridge) { - is MethodBridgeValueParameter.Mapped -> when (parameterDescriptor) { - null -> error("Mapped ValueParameter $parameterBridge has no descriptor.") - is ReceiverParameterDescriptor -> KirValueParameter.Kind.Receiver - is PropertySetterDescriptor -> KirValueParameter.Kind.PropertySetterValue - else -> KirValueParameter.Kind.ValueParameter(parameterDescriptor) - } - MethodBridgeValueParameter.ErrorOutParameter -> KirValueParameter.Kind.ErrorOut - is MethodBridgeValueParameter.SuspendCompletion -> KirValueParameter.Kind.SuspendCompletion - }, - configuration = getValueParameterConfiguration(parameterDescriptor, function), - ) + createValueParameter(parameterBridge, parameterDescriptor, function, descriptor) + } + } + + context(KirTypeParameterScope) + private fun createValueParameter( + parameterBridge: MethodBridgeValueParameter, + parameterDescriptor: ParameterDescriptor?, + function: KirFunction<*>, + functionDescriptor: FunctionDescriptor, + ) { + val kind = when (parameterBridge) { + is MethodBridgeValueParameter.Mapped -> when (parameterDescriptor) { + null -> error("Mapped ValueParameter $parameterBridge has no descriptor.") + is ReceiverParameterDescriptor -> KirValueParameter.Kind.Receiver + is PropertySetterDescriptor -> KirValueParameter.Kind.PropertySetterValue + else -> KirValueParameter.Kind.ValueParameter } + MethodBridgeValueParameter.ErrorOutParameter -> KirValueParameter.Kind.ErrorOut + is MethodBridgeValueParameter.SuspendCompletion -> KirValueParameter.Kind.SuspendCompletion + } + + val kotlinName = when (kind) { + is KirValueParameter.Kind.ValueParameter -> parameterDescriptor!!.name.asString() + KirValueParameter.Kind.Receiver -> "receiver" + KirValueParameter.Kind.PropertySetterValue -> "value" + KirValueParameter.Kind.ErrorOut -> "error" + KirValueParameter.Kind.SuspendCompletion -> "completionHandler" + } + + val valueParameter = KirValueParameter( + kotlinName = kotlinName, + objCName = when (kind) { + is KirValueParameter.Kind.ValueParameter -> namer.getOirValueParameterName(parameterDescriptor!!) + else -> kotlinName + }.toValidSwiftIdentifier(), + parent = function, + type = kirDeclarationTypeTranslator.mapValueParameterType(functionDescriptor, parameterDescriptor, parameterBridge), + kind = kind, + configuration = getValueParameterConfiguration(parameterDescriptor, function), + wasTypeInlined = parameterDescriptor?.type?.constructor?.declarationDescriptor?.isValueClass() == true, + ) + + parameterDescriptor?.let { + descriptorKirProvider.registerValueParameter(valueParameter, parameterDescriptor) + } } private fun getValueParameterConfiguration( @@ -313,6 +407,11 @@ class CreateKirMembersPhase( annotation.annotationClass?.annotations?.any { it.fqName == KonanFqNames.refinesInSwift } == true } + private val CallableMemberDescriptor.signature: String + get() = with(KonanManglerDesc) { + this@signature.signatureString(false) + } + private val MethodBridge.ReturnValue.errorHandlingStrategy: OirFunction.ErrorHandlingStrategy get() = when (this) { MethodBridge.ReturnValue.WithError.Success -> OirFunction.ErrorHandlingStrategy.ReturnsBoolean diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateKirTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateKirTypesPhase.kt deleted file mode 100644 index 712eafce8..000000000 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/kir/CreateKirTypesPhase.kt +++ /dev/null @@ -1,162 +0,0 @@ -package co.touchlab.skie.phases.kir - -import co.touchlab.skie.configuration.ClassConfiguration -import co.touchlab.skie.configuration.FileConfiguration -import co.touchlab.skie.configuration.FileOrClassConfiguration -import co.touchlab.skie.configuration.ModuleConfiguration -import co.touchlab.skie.configuration.PackageConfiguration -import co.touchlab.skie.kir.element.KirClass -import co.touchlab.skie.kir.element.KirEnumEntry -import co.touchlab.skie.kir.element.KirTypeParameter -import co.touchlab.skie.kir.type.ReferenceKirType -import co.touchlab.skie.phases.SirPhase -import co.touchlab.skie.phases.runtime.belongsToSkieKotlinRuntime -import org.jetbrains.kotlin.backend.konan.descriptors.enumEntries -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.SourceFile -import org.jetbrains.kotlin.descriptors.isSealed -import org.jetbrains.kotlin.resolve.descriptorUtil.module - -class CreateKirTypesPhase( - context: SirPhase.Context, -) : SirPhase { - - private val descriptorProvider = context.descriptorProvider - private val kirProvider = context.kirProvider - private val kotlinBuiltins = context.kotlinBuiltins - private val namer = context.namer - private val descriptorConfigurationProvider = context.descriptorConfigurationProvider - private val rootConfiguration = context.rootConfiguration - - private val baseType = ReferenceKirType(kotlinBuiltins.anyType) - - private val descriptorsToClasses = mutableMapOf() - - private val sourceFileConfiguration = ClassConfiguration( - FileOrClassConfiguration.File( - FileConfiguration(PackageConfiguration(ModuleConfiguration(rootConfiguration))), - ), - ) - - context(SirPhase.Context) - override suspend fun execute() { - createRegularClasses() - createFileClasses() - configureSealedSubclasses() - - kirProvider.initializeClassCache() - } - - private fun createRegularClasses() { - descriptorProvider.exposedClasses.forEach(::getOrCreateClass) - } - - private fun createFileClasses() { - descriptorProvider.exposedFiles.forEach(::createClass) - } - - private fun getOrCreateClass(descriptor: ClassDescriptor): KirClass = - descriptorsToClasses.getOrPut(descriptor) { - createClass(descriptor) - } - - private fun createClass(descriptor: ClassDescriptor): KirClass { - val parent = (descriptor.containingDeclaration as? ClassDescriptor) - ?.takeIf { it in descriptorProvider.exposedClasses } - ?.let { getOrCreateClass(it) } - ?: kirProvider.getModule(descriptor.module) - - val kirClass = KirClass( - descriptor = KirClass.Descriptor.Class(descriptor.original), - name = namer.getClassOrProtocolName(descriptor), - parent = parent, - kind = when (descriptor.kind) { - ClassKind.CLASS -> KirClass.Kind.Class - ClassKind.INTERFACE -> KirClass.Kind.Interface - ClassKind.ENUM_CLASS -> KirClass.Kind.Enum - ClassKind.OBJECT -> if (descriptor.isCompanionObject) KirClass.Kind.CompanionObject else KirClass.Kind.Object - ClassKind.ENUM_ENTRY, ClassKind.ANNOTATION_CLASS -> error("Unexpected class kind: ${descriptor.kind}") - }, - superTypes = descriptor.defaultType.constructor.supertypes.map { ReferenceKirType(it) }, - isSealed = descriptor.isSealed(), - hasUnexposedSealedSubclasses = descriptor.sealedSubclasses.any { !it.isExposed }, - belongsToSkieKotlinRuntime = descriptor.belongsToSkieKotlinRuntime, - configuration = descriptorConfigurationProvider.getConfiguration(descriptor), - ) - - configureClassParent(kirClass) - - createTypeParameters(kirClass, descriptor) - - createEnumEntries(kirClass, descriptor) - - return kirClass - } - - private fun createEnumEntries(kirClass: KirClass, descriptor: ClassDescriptor) { - if (kirClass.kind != KirClass.Kind.Enum) { - return - } - - descriptor.enumEntries.forEachIndexed { index, classDescriptor -> - KirEnumEntry( - descriptor = classDescriptor.original, - owner = kirClass, - index = index, - ) - } - } - - private fun createTypeParameters(kirClass: KirClass, descriptor: ClassDescriptor) { - if (kirClass.kind != KirClass.Kind.Class) { - return - } - - descriptor.typeConstructor.parameters.forEach { typeParameter -> - KirTypeParameter( - descriptor = typeParameter, - parent = kirClass, - ) - } - } - - private fun configureClassParent(kirClass: KirClass) { - if (kirClass.parent is KirClass) { - if (kirClass.kind == KirClass.Kind.CompanionObject) { - kirClass.parent.companionObject = kirClass - } - } - } - - private fun createClass(file: SourceFile) { - val module = kirProvider.getModule(descriptorProvider.getFileModule(file)) - - KirClass( - descriptor = KirClass.Descriptor.File(file), - name = namer.getFileClassName(file), - parent = module, - kind = KirClass.Kind.File, - superTypes = listOf(baseType), - isSealed = false, - hasUnexposedSealedSubclasses = false, - belongsToSkieKotlinRuntime = module.isSkieKotlinRuntime, - configuration = sourceFileConfiguration, - ) - } - - private fun configureSealedSubclasses() { - descriptorsToClasses.forEach { - configureSealedSubclasses(it.value, it.key) - } - } - - private fun configureSealedSubclasses(kirClass: KirClass, classDescriptor: ClassDescriptor) { - kirClass.sealedSubclasses.addAll( - classDescriptor.sealedSubclasses.mapNotNull { descriptorsToClasses[it] }, - ) - } - - private val ClassDescriptor.isExposed: Boolean - get() = this in descriptorProvider.exposedClasses -} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/RenameConflictingCallableDeclarationsPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/RenameConflictingCallableDeclarationsPhase.kt index 8fba01b86..d8cbbcfbe 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/RenameConflictingCallableDeclarationsPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/memberconflicts/RenameConflictingCallableDeclarationsPhase.kt @@ -2,12 +2,6 @@ package co.touchlab.skie.phases.memberconflicts import co.touchlab.skie.kir.element.KirCallableDeclaration import co.touchlab.skie.kir.element.KirFunction -import co.touchlab.skie.kir.type.BlockPointerKirType -import co.touchlab.skie.kir.type.ErrorOutKirType -import co.touchlab.skie.kir.type.KirType -import co.touchlab.skie.kir.type.OirBasedKirType -import co.touchlab.skie.kir.type.ReferenceKirType -import co.touchlab.skie.kir.type.SuspendCompletionKirType import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.sir.element.SirCallableDeclaration import co.touchlab.skie.sir.element.SirClass @@ -23,9 +17,6 @@ import co.touchlab.skie.sir.element.isRemoved import co.touchlab.skie.sir.element.module import co.touchlab.skie.sir.element.receiverDeclaration import co.touchlab.skie.sir.element.resolveAsSirClass -import org.jetbrains.kotlin.backend.konan.serialization.KonanManglerDesc -import org.jetbrains.kotlin.resolve.isValueClass -import org.jetbrains.kotlin.types.KotlinType object RenameConflictingCallableDeclarationsPhase : SirPhase { @@ -100,14 +91,10 @@ object RenameConflictingCallableDeclarationsPhase : SirPhase { } } .thenBy { declaration -> - (declaration.getKirDeclarationOrNull() as? KirFunction<*>)?.valueParameters?.count { it.type.isInlinedType } ?: 0 + (declaration.getKirDeclarationOrNull() as? KirFunction<*>)?.valueParameters?.count { it.wasTypeInlined } ?: 0 } .thenBy { it.parent.containerFqName } - .thenBy { - with(KonanManglerDesc) { - it.getKirDeclarationOrNull()?.descriptor?.signatureString(false) - } ?: "" - } + .thenBy { it.getKirDeclarationOrNull()?.kotlinSignature ?: "" } private val SirCallableDeclaration.isFromKotlin: Boolean get() = module is SirModule.Kotlin @@ -125,18 +112,6 @@ object RenameConflictingCallableDeclarationsPhase : SirPhase { private fun SirCallableDeclaration.getKirDeclarationOrNull(): KirCallableDeclaration<*>? = kirProvider.findCallableDeclaration(this) - private val KirType.isInlinedType: Boolean - get() = when (this) { - is BlockPointerKirType -> this.kotlinType.isInlinedType - ErrorOutKirType -> false - is OirBasedKirType -> false - is ReferenceKirType -> this.kotlinType.isInlinedType - is SuspendCompletionKirType -> this.kotlinType.isInlinedType - } - - private val KotlinType.isInlinedType: Boolean - get() = this.constructor.declarationDescriptor?.isValueClass() == true - @Suppress("RecursivePropertyAccessor") private val SirDeclarationParent.containerFqName: String get() = (this.parent?.containerFqName ?: "") + this.toString() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/ConfigureCInteropFrameworkNameForPlatformTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/ConfigureCInteropFrameworkNameForPlatformTypesPhase.kt index abae9ca79..b69e0cd0b 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/ConfigureCInteropFrameworkNameForPlatformTypesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/ConfigureCInteropFrameworkNameForPlatformTypesPhase.kt @@ -1,40 +1,26 @@ package co.touchlab.skie.phases.oir import co.touchlab.skie.configuration.ClassInterop -import co.touchlab.skie.configuration.provider.descriptor.configuration -import co.touchlab.skie.oir.element.OirClass +import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.phases.SirPhase -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe object ConfigureCInteropFrameworkNameForPlatformTypesPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - oirProvider.allExternalClassesAndProtocols.forEach { - configureIfPlatformType(it) + kirProvider.allPlatformClasses.forEach { + configureFrameworkName(it) } } context(SirPhase.Context) - private fun configureIfPlatformType(oirClass: OirClass) { - val origin = oirClass.origin as? OirClass.Origin.CinteropType ?: error("Invalid origin for OirClass: $oirClass") - - val classDescriptor = origin.classDescriptor - - if (!classDescriptor.isPlatformType) { - return - } - - classDescriptor.configuration[ClassInterop.CInteropFrameworkName] = classDescriptor.cinteropFrameworkName + private fun configureFrameworkName(kirClass: KirClass) { + kirClass.configuration[ClassInterop.CInteropFrameworkName] = kirClass.cinteropFrameworkName } - private val ClassDescriptor.isPlatformType: Boolean - get() = this.fqNameSafe.pathSegments()[0].asString() == "platform" - - private val ClassDescriptor.cinteropFrameworkName: String - get() = if (name.asString() != "NSObject") { - this.fqNameSafe.pathSegments()[1].asString() + private val KirClass.cinteropFrameworkName: String + get() = if (this.kotlinIdentifier != "NSObject") { + this.kotlinFqName.split(".")[1] } else { "Foundation" } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/ConfigureExternalOirTypesBridgingPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/ConfigureExternalOirTypesBridgingPhase.kt index 51322e6c6..a08693db1 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/ConfigureExternalOirTypesBridgingPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/ConfigureExternalOirTypesBridgingPhase.kt @@ -23,7 +23,7 @@ class ConfigureExternalOirTypesBridgingPhase( } private fun configureBridging() { - oirProvider.allExternalClassesAndProtocols.forEach(::configureBridging) + oirProvider.externalClassesAndProtocols.forEach(::configureBridging) } private fun configureBridging(oirClass: OirClass) { diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateExternalOirTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateExternalOirTypesPhase.kt new file mode 100644 index 000000000..c6e5d1070 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateExternalOirTypesPhase.kt @@ -0,0 +1,32 @@ +package co.touchlab.skie.phases.oir + +import co.touchlab.skie.kir.element.KirClass +import co.touchlab.skie.oir.element.OirClass +import co.touchlab.skie.oir.element.toOirKind +import co.touchlab.skie.phases.SirPhase + +object CreateExternalOirTypesPhase : SirPhase { + + context(SirPhase.Context) + override suspend fun execute() { + kirProvider.allExternalClasses.forEach { + createClass(it) + } + + oirProvider.initializeExternalClassCache() + } + + context(SirPhase.Context) + private fun createClass(kirClass: KirClass) { + val oirClass = OirClass( + name = kirClass.objCName, + parent = oirProvider.externalModule, + kind = kirClass.kind.toOirKind(), + origin = OirClass.Origin.Kir(kirClass), + ) + + kirClass.oirClass = oirClass + + CreateKotlinOirTypesPhase.createTypeParameters(kirClass, oirClass) + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateFakeObjCConstructorsPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateFakeObjCConstructorsPhase.kt index d6767dfc6..97886fafb 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateFakeObjCConstructorsPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateFakeObjCConstructorsPhase.kt @@ -14,7 +14,7 @@ object CreateFakeObjCConstructorsPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - oirProvider.allKotlinClasses.forEach { + oirProvider.kotlinClasses.forEach { it.addFakeObjCConstructors() } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateKotlinOirTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateKotlinOirTypesPhase.kt new file mode 100644 index 000000000..27c2707c8 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateKotlinOirTypesPhase.kt @@ -0,0 +1,61 @@ +package co.touchlab.skie.phases.oir + +import co.touchlab.skie.kir.element.KirClass +import co.touchlab.skie.oir.element.OirClass +import co.touchlab.skie.oir.element.OirTypeParameter +import co.touchlab.skie.oir.element.toOirKind +import co.touchlab.skie.phases.SirPhase + +class CreateKotlinOirTypesPhase( + context: SirPhase.Context, +) : SirPhase { + + private val kirProvider = context.kirProvider + private val oirProvider = context.oirProvider + + context(SirPhase.Context) + override suspend fun execute() { + createClasses() + + oirProvider.initializeKotlinClassCache() + } + + private fun createClasses() { + kirProvider.kotlinClasses.forEach(::createClass) + } + + private fun createClass(kirClass: KirClass): OirClass { + val module = oirProvider.getKotlinModule(kirClass.module) + + val oirClass = OirClass( + name = kirClass.objCName, + parent = oirProvider.getFile(module, kirClass.swiftName), + kind = kirClass.kind.toOirKind(), + origin = OirClass.Origin.Kir(kirClass), + ) + + createTypeParameters(kirClass, oirClass) + + kirClass.oirClass = oirClass + + return oirClass + } + + companion object { + + fun createTypeParameters(kirClass: KirClass, oirClass: OirClass) { + kirClass.typeParameters.forEach { typeParameter -> + OirTypeParameter( + name = typeParameter.name, + parent = oirClass, + variance = typeParameter.variance, + // Bounds are not supported. + ) + } + + kirClass.typeParameters.zip(oirClass.typeParameters).forEach { (kirTypeParameter, oirTypeParameter) -> + kirTypeParameter.oirTypeParameter = oirTypeParameter + } + } + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateOirMembersPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateOirMembersPhase.kt index a8a4bcfc5..f60c55c73 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateOirMembersPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateOirMembersPhase.kt @@ -21,12 +21,7 @@ import co.touchlab.skie.oir.element.OirProperty import co.touchlab.skie.oir.element.OirScope import co.touchlab.skie.oir.element.OirSimpleFunction import co.touchlab.skie.oir.element.OirValueParameter -import co.touchlab.skie.oir.element.kirClassOrNull -import co.touchlab.skie.oir.type.translation.OirTypeParameterScope -import co.touchlab.skie.oir.type.translation.typeParameterScope import co.touchlab.skie.phases.SirPhase -import co.touchlab.skie.phases.oir.util.getOirValueParameterName -import co.touchlab.skie.util.swift.toValidSwiftIdentifier import org.jetbrains.kotlin.backend.konan.cKeywords class CreateOirMembersPhase( @@ -34,7 +29,6 @@ class CreateOirMembersPhase( ) : SirPhase { private val kirProvider = context.kirProvider - private val namer = context.namer private val oirTypeTranslator = context.oirTypeTranslator private val extensionCache = mutableMapOf() @@ -47,7 +41,7 @@ class CreateOirMembersPhase( } private fun createAllMembers() { - kirProvider.allCallableDeclarations.forEach(::createCallableDeclaration) + kirProvider.kotlinCallableDeclarations.forEach(::createCallableDeclaration) } private fun createCallableDeclaration(kirCallableDeclaration: KirCallableDeclaration<*>) { @@ -60,7 +54,7 @@ class CreateOirMembersPhase( private fun createConstructor(constructor: KirConstructor) { val oirConstructor = OirConstructor( - selector = namer.getSelector(constructor.baseDescriptor), + selector = constructor.objCSelector, parent = constructor.owner.oirClass, errorHandlingStrategy = constructor.errorHandlingStrategy, deprecationLevel = constructor.deprecationLevel, @@ -73,10 +67,10 @@ class CreateOirMembersPhase( private fun createFunction(function: KirSimpleFunction) { val oirSimpleFunction = OirSimpleFunction( - selector = namer.getSelector(function.baseDescriptor), + selector = function.objCSelector, parent = getOirCallableDeclarationParent(function), scope = function.oirScope, - returnType = oirTypeTranslator.mapType(function.returnType, function.owner.oirClass.genericsScope), + returnType = oirTypeTranslator.mapType(function.returnType), errorHandlingStrategy = function.errorHandlingStrategy, deprecationLevel = function.deprecationLevel, ) @@ -88,8 +82,8 @@ class CreateOirMembersPhase( private fun createProperty(property: KirProperty) { property.oirProperty = OirProperty( - name = namer.getPropertyName(property.baseDescriptor).objCName, - type = oirTypeTranslator.mapType(property.type, property.owner.oirClass.genericsScope), + name = property.objCName, + type = oirTypeTranslator.mapType(property.type), isVar = property.isVar, parent = getOirCallableDeclarationParent(property), scope = property.oirScope, @@ -121,13 +115,11 @@ class CreateOirMembersPhase( val labels = listOf("") + oirFunction.selector.trimEnd(':').split(':').drop(1) val usedNames = mutableSetOf() - val oirGenericsScope = oirFunction.owner.genericsScope - valueParameters.forEachIndexed { index, valueParameter -> val oirValueParameter = OirValueParameter( label = labels[index], name = getValueParameterName(valueParameter, usedNames), - type = oirTypeTranslator.mapType(valueParameter.type, oirGenericsScope), + type = oirTypeTranslator.mapType(valueParameter.type), parent = oirFunction, index = index, ) @@ -137,12 +129,7 @@ class CreateOirMembersPhase( } private fun getValueParameterName(kirValueParameter: KirValueParameter, usedNames: MutableSet): String { - val candidateName = when (kirValueParameter.kind) { - is KirValueParameter.Kind.ValueParameter -> namer.getOirValueParameterName(kirValueParameter.kind.descriptor) - else -> kirValueParameter.name - } - - var uniqueName = candidateName.toValidSwiftIdentifier() + var uniqueName = kirValueParameter.objCName while (uniqueName in usedNames || uniqueName in cKeywords) { uniqueName += "_" } @@ -153,7 +140,7 @@ class CreateOirMembersPhase( } private fun createAllEnumEntries() { - kirProvider.allEnums.forEach(::createEnumEntries) + kirProvider.kotlinEnums.forEach(::createEnumEntries) } private fun createEnumEntries(kirClass: KirClass) { @@ -162,7 +149,7 @@ class CreateOirMembersPhase( private fun createEnumEntry(enumEntry: KirEnumEntry) { enumEntry.oirEnumEntry = OirProperty( - name = namer.getEnumEntrySelector(enumEntry.descriptor), + name = enumEntry.objCSelector, type = enumEntry.owner.oirClass.defaultType, isVar = false, parent = enumEntry.owner.oirClass, @@ -172,7 +159,7 @@ class CreateOirMembersPhase( } private fun initializeOverridesForAllMembers() { - kirProvider.allOverridableDeclaration.forEach(::initializeOverrides) + kirProvider.kotlinOverridableDeclaration.forEach(::initializeOverrides) } private fun initializeOverrides(overridableDeclaration: KirOverridableDeclaration<*, *>) { @@ -200,7 +187,4 @@ class CreateOirMembersPhase( } else { OirScope.Member } - - private val OirClass.genericsScope: OirTypeParameterScope - get() = this.kirClassOrNull?.typeParameterScope ?: error("OirClass $this does not originate from KirClass.") } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateOirTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateOirTypesPhase.kt deleted file mode 100644 index ef4053de8..000000000 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/CreateOirTypesPhase.kt +++ /dev/null @@ -1,105 +0,0 @@ -package co.touchlab.skie.phases.oir - -import co.touchlab.skie.kir.element.KirClass -import co.touchlab.skie.oir.element.OirClass -import co.touchlab.skie.oir.element.OirTypeParameter -import co.touchlab.skie.oir.element.superClass -import co.touchlab.skie.oir.type.DeclaredOirType -import co.touchlab.skie.oir.type.translation.typeParameterScope -import co.touchlab.skie.phases.SirPhase -import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExportNamer -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.types.Variance - -class CreateOirTypesPhase( - context: SirPhase.Context, -) : SirPhase { - - private val kirProvider = context.kirProvider - private val kirBuiltins = context.kirBuiltins - private val oirProvider = context.oirProvider - private val namer = context.namer - private val oirTypeTranslator = context.oirTypeTranslator - - context(SirPhase.Context) - override suspend fun execute() { - createClasses() - - initializeSuperTypesForAllClasses() - - oirProvider.initializeKotlinClassCache() - } - - private fun createClasses() { - kirProvider.allClasses.forEach(::createClass) - } - - private fun createClass(kirClass: KirClass): OirClass { - val module = oirProvider.getModule(kirClass.module) - - val oirClass = OirClass( - name = kirClass.name.objCName, - parent = oirProvider.getFile(module, kirClass.name.swiftName), - kind = when (kirClass.kind) { - KirClass.Kind.Interface -> OirClass.Kind.Protocol - else -> OirClass.Kind.Class - }, - origin = OirClass.Origin.Kir(kirClass), - ) - - createTypeParameters(oirClass, kirClass) - - kirClass.oirClass = oirClass - - return oirClass - } - - private fun createTypeParameters(oirClass: OirClass, kirClass: KirClass) { - val typeParameters = kirClass.typeParameters.map { it.descriptor } - - createTypeParameters(oirClass, typeParameters, namer) - - kirClass.typeParameters.zip(oirClass.typeParameters).forEach { (kirTypeParameter, oirTypeParameter) -> - kirTypeParameter.oirTypeParameter = oirTypeParameter - } - } - - private fun initializeSuperTypesForAllClasses() { - kirProvider.allClasses.forEach(::initializeSuperTypes) - } - - private fun initializeSuperTypes(kirClass: KirClass) { - val oirClass = kirClass.oirClass - val oirGenericsScope = kirClass.typeParameterScope - - val superTypesWithoutAny = kirClass.superTypes - .filter { !KotlinBuiltIns.isAnyOrNullableAny(it.kotlinType) } - .map { oirTypeTranslator.mapType(it, oirGenericsScope) } - .filterIsInstance() - - oirClass.superTypes.addAll(superTypesWithoutAny) - - if (oirClass.kind == OirClass.Kind.Class && oirClass.superClass == null && kirClass != kirBuiltins.Base) { - oirClass.superTypes.add(kirBuiltins.Base.oirClass.defaultType) - } - } - - companion object { - - fun createTypeParameters(oirClass: OirClass, typeParameters: List, namer: ObjCExportNamer) { - typeParameters.forEach { typeParameter -> - OirTypeParameter( - name = namer.getTypeParameterName(typeParameter), - parent = oirClass, - variance = when (typeParameter.variance) { - Variance.INVARIANT -> OirTypeParameter.Variance.Invariant - Variance.IN_VARIANCE -> OirTypeParameter.Variance.Contravariant - Variance.OUT_VARIANCE -> OirTypeParameter.Variance.Covariant - }, - // Bounds are not supported yet. - ) - } - } - } -} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/FixOirFunctionSignaturesForApiNotesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/FixOirFunctionSignaturesForApiNotesPhase.kt index 577f2c5e4..70ff1fb2c 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/FixOirFunctionSignaturesForApiNotesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/FixOirFunctionSignaturesForApiNotesPhase.kt @@ -33,7 +33,7 @@ class FixOirFunctionSignaturesForApiNotesPhase( context(SirPhase.Context) override suspend fun execute() { - oirProvider.allKotlinClassesAndProtocols.forEach { + oirProvider.kotlinClassesAndProtocols.forEach { fixFunctionSignatures(it) } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/InitializeOirSuperTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/InitializeOirSuperTypesPhase.kt new file mode 100644 index 000000000..0039a06b3 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/InitializeOirSuperTypesPhase.kt @@ -0,0 +1,25 @@ +package co.touchlab.skie.phases.oir + +import co.touchlab.skie.kir.element.KirClass +import co.touchlab.skie.phases.SirPhase + +object InitializeOirSuperTypesPhase : SirPhase { + + context(SirPhase.Context) + override suspend fun execute() { + kirProvider.allClasses.forEach { + initializeSuperTypes(it) + } + } + + context(SirPhase.Context) + private fun initializeSuperTypes(kirClass: KirClass) { + val oirClass = kirClass.oirClass + + kirClass.superTypes + .map { oirTypeTranslator.mapType(it) } + .forEach { superType -> + oirClass.superTypes.add(superType) + } + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/util/ExternalApiNotesProvider.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/util/ExternalApiNotesProvider.kt index 8f1906f0c..a58e2e3b4 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/util/ExternalApiNotesProvider.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/oir/util/ExternalApiNotesProvider.kt @@ -1,6 +1,7 @@ package co.touchlab.skie.phases.oir.util import co.touchlab.skie.oir.element.OirClass +import co.touchlab.skie.oir.element.kirClassOrNull import co.touchlab.skie.phases.apinotes.builder.ApiNotes import co.touchlab.skie.phases.apinotes.builder.ApiNotesType import co.touchlab.skie.phases.apinotes.parser.ExternalApiNotesParser @@ -26,7 +27,7 @@ class ExternalApiNotesProvider( apiNotesModuleProvidersByModuleName.values.map { it.value }.flatMap { it.getAllApiNotesEntries() } fun findApiNotesEntry(oirClass: OirClass): ApiNotesEntry? { - val module = sirProvider.findExternalModule(oirClass) ?: return null + val module = oirClass.kirClassOrNull?.let { sirProvider.findExternalModule(it) } ?: return null return apiNotesModuleProvidersByModuleName[module.name]?.value?.findApiNotesEntry(oirClass) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ConfigureSwiftSpecificLinkerArgsPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ConfigureSwiftSpecificLinkerArgsPhase.kt new file mode 100644 index 000000000..99afa23b7 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ConfigureSwiftSpecificLinkerArgsPhase.kt @@ -0,0 +1,24 @@ +package co.touchlab.skie.phases.other + +import co.touchlab.skie.phases.LinkPhase +import org.jetbrains.kotlin.backend.konan.KonanConfigKeys +import org.jetbrains.kotlin.konan.target.platformName +import java.io.File + +object ConfigureSwiftSpecificLinkerArgsPhase : LinkPhase { + + context(LinkPhase.Context) + override suspend fun execute() { + val swiftLibSearchPaths = listOf( + File(configurables.absoluteTargetToolchain, "usr/lib/swift/${configurables.platformName().lowercase()}"), + File(configurables.absoluteTargetSysRoot, "usr/lib/swift"), + ).flatMap { listOf("-L", it.absolutePath) } + + val otherLinkerFlags = listOf( + "-rpath", "/usr/lib/swift", "-dead_strip", + ) + + konanConfig.configuration.addAll(KonanConfigKeys.LINKER_ARGS, swiftLibSearchPaths) + konanConfig.configuration.addAll(KonanConfigKeys.LINKER_ARGS, otherLinkerFlags) + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ExtraClassExportPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ExtraClassExportPhase.kt index 2a0cf3264..06e47cf4a 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ExtraClassExportPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ExtraClassExportPhase.kt @@ -8,6 +8,7 @@ import co.touchlab.skie.kir.irbuilder.createFunction import co.touchlab.skie.kir.irbuilder.util.createValueParameter import co.touchlab.skie.phases.ClassExportPhase import co.touchlab.skie.phases.features.flow.SupportedFlow +import co.touchlab.skie.phases.util.StatefulDescriptorConversionPhase import co.touchlab.skie.phases.util.StatefulSirPhase import co.touchlab.skie.phases.util.doInPhase import co.touchlab.skie.sir.element.SirVisibility @@ -158,12 +159,18 @@ class ExtraClassExportPhase( } private fun FunctionDescriptor.removeFromSwift() { - context.doInPhase(FinalizePhase) { - kirProvider.getFunction(this@removeFromSwift).originalSirFunction.visibility = SirVisibility.Private + context.doInPhase(HideExportFunctionsInitPhase) { + val kirFunction = descriptorKirProvider.getFunction(this@removeFromSwift) + + doInPhase(HideExportFunctionsFinalizePhase) { + kirFunction.originalSirFunction.visibility = SirVisibility.Private + } } } - object FinalizePhase : StatefulSirPhase() + object HideExportFunctionsInitPhase : StatefulDescriptorConversionPhase() + + object HideExportFunctionsFinalizePhase : StatefulSirPhase() } private fun CallableMemberDescriptor.getAllFlowArgumentClasses(): List = diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/FixDuplicatedOverriddenFunctionsPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/FixDuplicatedOverriddenFunctionsPhase.kt index b28e0f448..1f3229d80 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/FixDuplicatedOverriddenFunctionsPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/FixDuplicatedOverriddenFunctionsPhase.kt @@ -8,14 +8,14 @@ import co.touchlab.skie.sir.element.SirVisibility import co.touchlab.skie.sir.element.copyValueParametersFrom import co.touchlab.skie.sir.element.shallowCopy -// Fix for SKIE-395. +// Fix for a compiler bug (SKIE-395). // The implementation is somewhat hacky because it creates a fake function that is used to remove the duplicates. // This fake function is not properly linked with the overrides and as a result this phase needs to run after all other phases that rename functions. object FixDuplicatedOverriddenFunctionsPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - oirProvider.allKotlinClassesAndProtocols + oirProvider.kotlinClassesAndProtocols .flatMap { it.memberSimpleFunctions } .forEach { fixDuplicates(it) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ProcessReportedMessagesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ProcessReportedMessagesPhase.kt new file mode 100644 index 000000000..e2f9246ca --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/ProcessReportedMessagesPhase.kt @@ -0,0 +1,41 @@ +package co.touchlab.skie.phases.other + +import co.touchlab.skie.phases.LinkPhase +import co.touchlab.skie.util.Reporter +import co.touchlab.skie.util.Reporter.Severity +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageUtil +import org.jetbrains.kotlin.cli.jvm.compiler.report +import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi +import org.jetbrains.kotlin.renderer.DescriptorRenderer + +object ProcessReportedMessagesPhase : LinkPhase { + + context(LinkPhase.Context) + override suspend fun execute() { + reporter.reports.forEach { + report(it) + } + } + + context(LinkPhase.Context) + private fun report(report: Reporter.Report) { + val declaration = report.source?.let { descriptorKirProvider.findDeclarationDescriptor(it) } + + val location = MessageUtil.psiElementToMessageLocation(declaration?.findPsi())?.let { + CompilerMessageLocation.create(it.path, it.line, it.column, it.lineContent) + } + + val message = if (declaration != null && location == null) { + "${report.message}\n (at ${DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(declaration)})" + } else { + report.message + } + + when (report.severity) { + Severity.Error -> konanConfig.configuration.report(CompilerMessageSeverity.ERROR, message, location) + Severity.Warning -> konanConfig.configuration.report(CompilerMessageSeverity.WARNING, message, location) + } + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/VerifyNoBitcodeEmbeddingPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/VerifyNoBitcodeEmbeddingPhase.kt index 66d52c4f3..018f2422c 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/VerifyNoBitcodeEmbeddingPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/other/VerifyNoBitcodeEmbeddingPhase.kt @@ -2,15 +2,12 @@ package co.touchlab.skie.phases.other import co.touchlab.skie.phases.ClassExportPhase import org.jetbrains.kotlin.backend.konan.BitcodeEmbedding -import org.jetbrains.kotlin.backend.konan.KonanConfigKeys object VerifyNoBitcodeEmbeddingPhase : ClassExportPhase { context(ClassExportPhase.Context) override suspend fun execute() { - val bitcodeEmbeddingMode = compilerConfiguration[KonanConfigKeys.BITCODE_EMBEDDING_MODE] - - if (bitcodeEmbeddingMode == BitcodeEmbedding.Mode.FULL) { + if (swiftCompilerConfiguration.bitcodeEmbeddingMode == BitcodeEmbedding.Mode.FULL) { error( "Bitcode embedding is not supported by SKIE. " + "To disable bitcode embedding you likely need to remove `embedBitcode(BitcodeEmbeddingMode.BITCODE)` from the Gradle build script.", diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/runtime/ConfigureStableNameTypeAliasesForKotlinRuntimePhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/runtime/ConfigureStableNameTypeAliasesForKotlinRuntimePhase.kt index 118efcd3e..d985ce5ee 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/runtime/ConfigureStableNameTypeAliasesForKotlinRuntimePhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/runtime/ConfigureStableNameTypeAliasesForKotlinRuntimePhase.kt @@ -20,7 +20,6 @@ object ConfigureStableNameTypeAliasesForKotlinRuntimePhase : SirPhase { kirProvider.getClassByFqName("kotlinx.coroutines.Runnable").enableStableNameTypeAlias() } - context(SirPhase.Context) private fun KirClass.enableStableNameTypeAlias() { configuration[ClassInterop.StableTypeAlias] = true } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/runtime/KotlinRuntimeHidingPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/runtime/KotlinRuntimeHidingPhase.kt index 59dcf7205..14f225f38 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/runtime/KotlinRuntimeHidingPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/runtime/KotlinRuntimeHidingPhase.kt @@ -1,6 +1,7 @@ package co.touchlab.skie.phases.runtime import co.touchlab.skie.configuration.SkieConfigurationFlag +import co.touchlab.skie.kir.element.KirModule import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.sir.element.SirVisibility @@ -11,8 +12,8 @@ object KotlinRuntimeHidingPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - kirProvider.allClasses - .filter { it.belongsToSkieKotlinRuntime } + kirProvider.kotlinClasses + .filter { it.module.origin == KirModule.Origin.SkieRuntime } .forEach { it.originalSirClass.visibility = SirVisibility.PublicButHidden } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/CreateAsyncSirFunctionsPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/CreateAsyncSirFunctionsPhase.kt index b33010690..6ca8732ea 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/CreateAsyncSirFunctionsPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/CreateAsyncSirFunctionsPhase.kt @@ -11,7 +11,7 @@ object CreateAsyncSirFunctionsPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - kirProvider.allSimpleFunctions + kirProvider.kotlinSimpleFunctions .filter { it.isSuspend && it.configuration.isSuspendInteropEnabled } .forEach { createAsyncFunction(it) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/CreateSirMembersPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/CreateSirMembersPhase.kt index 38a274e52..65485262e 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/CreateSirMembersPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/CreateSirMembersPhase.kt @@ -29,9 +29,7 @@ class CreateSirMembersPhase( val context: SirPhase.Context, ) : SirPhase { - private val namer = context.namer private val kirProvider = context.kirProvider - private val sirProvider = context.sirProvider private val sirTypeTranslator = context.sirTypeTranslator context(SirPhase.Context) @@ -41,7 +39,7 @@ class CreateSirMembersPhase( } private fun createAllMembers() { - kirProvider.allCallableDeclarations.forEach(::createCallableDeclaration) + kirProvider.kotlinCallableDeclarations.forEach(::createCallableDeclaration) } private fun createCallableDeclaration(kirCallableDeclaration: KirCallableDeclaration<*>) { @@ -88,18 +86,16 @@ class CreateSirMembersPhase( val oirProperty = property.oirProperty val sirProperty = SirProperty( - identifier = namer.getPropertyName(property.baseDescriptor).swiftName, + identifier = property.swiftName, parent = property.getSirParent(), type = sirTypeTranslator.mapType(oirProperty.type), scope = oirProperty.scope.sirScope, deprecationLevel = property.deprecationLevel, visibility = property.visibility, ).apply { - property.descriptor.getter?.let { - SirGetter( - throws = false, - ) - } + SirGetter( + throws = false, + ) if (property.isVar) { SirSetter( @@ -141,7 +137,7 @@ class CreateSirMembersPhase( val sirValueParameter = SirValueParameter( label = argumentLabel, - name = valueParameter.name.toValidSwiftIdentifier().collisionFreeIdentifier(usedParameterNames), + name = valueParameter.kotlinName.toValidSwiftIdentifier().collisionFreeIdentifier(usedParameterNames), type = sirTypeTranslator.mapType(oirValueParameter.type, isEscaping = true), ) @@ -168,10 +164,8 @@ class CreateSirMembersPhase( private val KirFunction<*>.swiftFunctionName: SwiftFunctionName get() { - val swiftName = namer.getSwiftName(this.baseDescriptor) - - val (identifier, argumentLabelsString) = swiftNameComponentsRegex.matchEntire(swiftName)?.destructured - ?: error("Unable to parse swift name: $swiftName") + val (identifier, argumentLabelsString) = swiftNameComponentsRegex.matchEntire(this.swiftName)?.destructured + ?: error("Unable to parse swift name: ${this.swiftName}") val argumentLabels = argumentLabelsString.split(":").map { it.trim() }.filter { it.isNotEmpty() } @@ -179,7 +173,7 @@ class CreateSirMembersPhase( } private fun createAllEnumEntries() { - kirProvider.allEnums.forEach(::createEnumEntries) + kirProvider.kotlinEnums.forEach(::createEnumEntries) } private fun createEnumEntries(kirClass: KirClass) { @@ -190,7 +184,7 @@ class CreateSirMembersPhase( val oirEnumEntry = enumEntry.oirEnumEntry oirEnumEntry.originalSirProperty = SirProperty( - identifier = namer.getEnumEntrySwiftName(enumEntry.descriptor), + identifier = enumEntry.swiftName, parent = enumEntry.owner.originalSirClass, type = sirTypeTranslator.mapType(oirEnumEntry.type), scope = oirEnumEntry.scope.sirScope, diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/InitializeSirOverridesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/InitializeSirOverridesPhase.kt index 094c49bf0..1d6b70145 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/InitializeSirOverridesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/InitializeSirOverridesPhase.kt @@ -9,7 +9,7 @@ object InitializeSirOverridesPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - kirProvider.allOverridableDeclaration.forEach(::initializeOverrides) + kirProvider.kotlinOverridableDeclaration.forEach(::initializeOverrides) } private fun initializeOverrides(overridableDeclaration: KirOverridableDeclaration<*, *>) { diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/StripKonanCallableDeclarationManglingPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/StripKonanCallableDeclarationManglingPhase.kt index ab5fa96bc..127db078d 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/StripKonanCallableDeclarationManglingPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/member/StripKonanCallableDeclarationManglingPhase.kt @@ -12,7 +12,7 @@ object StripKonanCallableDeclarationManglingPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - kirProvider.allCallableDeclarations + kirProvider.kotlinCallableDeclarations .filter { it.isSupported } .forEach { it.stripMangling() @@ -31,7 +31,7 @@ object StripKonanCallableDeclarationManglingPhase : SirPhase { } private fun KirSimpleFunction.stripMangling() { - originalSirFunction.identifier = originalSirFunction.identifier.stripMangling(name) + originalSirFunction.identifier = originalSirFunction.identifier.stripMangling(kotlinName) valueParameters.forEach { it.stripMangling() @@ -47,11 +47,11 @@ object StripKonanCallableDeclarationManglingPhase : SirPhase { private fun KirValueParameter.stripMangling() { val sirValueParameter = originalSirValueParameter ?: return - sirValueParameter.label = sirValueParameter.labelOrName.stripMangling(this.name) + sirValueParameter.label = sirValueParameter.labelOrName.stripMangling(this.kotlinName) } private fun KirProperty.stripMangling() { - originalSirProperty.identifier = originalSirProperty.identifier.stripMangling(name) + originalSirProperty.identifier = originalSirProperty.identifier.stripMangling(kotlinName) } private fun String.stripMangling(kotlinName: String): String { diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateExternalSirTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateExternalSirTypesPhase.kt index e6d95bc32..9959ea869 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateExternalSirTypesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateExternalSirTypesPhase.kt @@ -1,6 +1,7 @@ package co.touchlab.skie.phases.sir.type import co.touchlab.skie.oir.element.OirClass +import co.touchlab.skie.oir.element.kirClassOrNull import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.sir.element.SirClass import co.touchlab.skie.sir.element.SirModule @@ -10,22 +11,22 @@ object CreateExternalSirTypesPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - oirProvider.allExternalClassesAndProtocols.forEach { + oirProvider.externalClassesAndProtocols.forEach { createClass(it) } } context(SirPhase.Context) - private fun createClass(oirClass: OirClass): SirClass { + private fun createClass(oirClass: OirClass) { val sirClass = SirClass( baseName = oirClass.name, - parent = sirProvider.findExternalModule(oirClass)?.builtInFile ?: SirModule.Unknown.builtInFile, + parent = oirClass.kirClassOrNull?.let { sirProvider.findExternalModule(it) }?.builtInFile ?: SirModule.Unknown.builtInFile, kind = oirClass.kind.toSirKind(), origin = SirClass.Origin.Oir(oirClass), ) oirClass.originalSirClass = sirClass - return sirClass + CreateKotlinSirTypesPhase.createTypeParameters(oirClass, sirClass) } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateKotlinSirExtensionsPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateKotlinSirExtensionsPhase.kt index 0034a30a8..103273d1f 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateKotlinSirExtensionsPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateKotlinSirExtensionsPhase.kt @@ -8,7 +8,7 @@ object CreateKotlinSirExtensionsPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - oirProvider.allKotlinExtensions.forEach { + oirProvider.kotlinExtensions.forEach { createExtension(it) } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateKotlinSirTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateKotlinSirTypesPhase.kt index ecb1ebaea..ae054c120 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateKotlinSirTypesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateKotlinSirTypesPhase.kt @@ -2,6 +2,7 @@ package co.touchlab.skie.phases.sir.type import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.kir.element.KirModule +import co.touchlab.skie.oir.element.OirClass import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.sir.SirFqName import co.touchlab.skie.sir.element.SirClass @@ -9,26 +10,24 @@ import co.touchlab.skie.sir.element.SirDeclarationParent import co.touchlab.skie.sir.element.SirTypeParameter import co.touchlab.skie.sir.element.toSirKind -class CreateKotlinSirTypesPhase( - val context: SirPhase.Context, -) : SirPhase { - - private val kirProvider = context.kirProvider - private val sirProvider = context.sirProvider - private val sirBuiltins = context.sirBuiltins +object CreateKotlinSirTypesPhase : SirPhase { private val kirToSirClasses = mutableMapOf() context(SirPhase.Context) override suspend fun execute() { - kirProvider.allClasses.forEach(::getOrCreateClass) + kirProvider.kotlinClasses.forEach { + getOrCreateClass(it) + } } + context(SirPhase.Context) private fun getOrCreateClass(kirClass: KirClass): SirClass = kirToSirClasses.getOrPut(kirClass) { createClass(kirClass) } + context(SirPhase.Context) private fun createClass(kirClass: KirClass): SirClass { val sirClass = SirClass( baseName = kirClass.sirFqName.simpleName, @@ -37,28 +36,18 @@ class CreateKotlinSirTypesPhase( origin = SirClass.Origin.Kir(kirClass), ) - sirClass.addTypeParameters(kirClass) + createTypeParameters(kirClass.oirClass, sirClass) kirClass.oirClass.originalSirClass = sirClass return sirClass } - private fun SirClass.addTypeParameters(kirClass: KirClass) { - kirClass.typeParameters.forEach { typeParameter -> - typeParameter.oirTypeParameter.sirTypeParameter = SirTypeParameter( - name = typeParameter.oirTypeParameter.name, - bounds = listOf(sirBuiltins.Swift.AnyObject.defaultType), - ) - } - } - + context(SirPhase.Context) private val KirClass.sirFqName: SirFqName get() { - val swiftName = name.swiftName - - val firstComponent = swiftName.substringBefore(".") - val secondComponent = swiftName.substringAfter(".").takeIf { it.isNotBlank() } + val firstComponent = this.swiftName.substringBefore(".") + val secondComponent = this.swiftName.substringAfter(".").takeIf { it.isNotBlank() } val firstName = SirFqName( module = sirProvider.kotlinModule, @@ -68,12 +57,25 @@ class CreateKotlinSirTypesPhase( return if (secondComponent != null) firstName.nested(secondComponent) else firstName } + context(SirPhase.Context) private val KirClass.sirParent: SirDeclarationParent get() = sirFqName.parent?.simpleName?.let { findSirParentRecursively(this, it) } ?: sirProvider.kotlinModule.builtInFile + context(SirPhase.Context) private fun findSirParentRecursively(kirClass: KirClass, parentName: String): SirClass? = when (val parent = kirClass.parent) { - is KirClass -> if (parent.name.swiftName == parentName) getOrCreateClass(parent) else findSirParentRecursively(parent, parentName) + is KirClass -> if (parent.swiftName == parentName) getOrCreateClass(parent) else findSirParentRecursively(parent, parentName) is KirModule -> null } + + context(SirPhase.Context) + fun createTypeParameters(oirClass: OirClass, sirClass: SirClass) { + oirClass.typeParameters.forEach { typeParameter -> + typeParameter.sirTypeParameter = SirTypeParameter( + name = typeParameter.name, + parent = sirClass, + bounds = listOf(sirBuiltins.Swift.AnyObject.defaultType), + ) + } + } } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateStableTypeAliasesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateStableTypeAliasesPhase.kt index 0cbc5a5c3..bde03191e 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateStableTypeAliasesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/CreateStableTypeAliasesPhase.kt @@ -20,7 +20,7 @@ object CreateStableNameTypeAliasesPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - kirProvider.allClasses + kirProvider.kotlinClasses .filter { it.hasStableNameTypeAlias || shouldGenerateFileForEachExportedClass } .forEach { createTypeAlias(it) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/FixNamesOfInaccessibleNestedClassesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/FixNamesOfInaccessibleNestedClassesPhase.kt index e9fab91cd..0349817e7 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/FixNamesOfInaccessibleNestedClassesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/FixNamesOfInaccessibleNestedClassesPhase.kt @@ -10,11 +10,11 @@ object FixNamesOfInaccessibleNestedClassesPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { - kirProvider.allClasses.forEach(::fixNameOfInaccessibleNestedClass) + kirProvider.kotlinClasses.forEach(::fixNameOfInaccessibleNestedClass) } private fun fixNameOfInaccessibleNestedClass(kirClass: KirClass) { - val swiftName = kirClass.name.swiftName + val swiftName = kirClass.swiftName val hasIncorrectName = swiftName.contains(".") && swiftName != kirClass.originalSirClass.fqName.toLocalString() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/InitializeSirTypesSuperTypesForOirPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/InitializeSirSuperTypesPhase.kt similarity index 95% rename from SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/InitializeSirTypesSuperTypesForOirPhase.kt rename to SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/InitializeSirSuperTypesPhase.kt index faac7aa07..7d2bd2a6e 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/InitializeSirTypesSuperTypesForOirPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/sir/type/InitializeSirSuperTypesPhase.kt @@ -4,7 +4,7 @@ import co.touchlab.skie.oir.element.OirClass import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.sir.type.SirDeclaredSirType -object InitializeSirTypesSuperTypesForOirPhase : SirPhase { +object InitializeSirSuperTypesPhase : SirPhase { context(SirPhase.Context) override suspend fun execute() { diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/swift/CompileSwiftPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/swift/CompileSwiftPhase.kt index 00554af8c..e7f9957d5 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/swift/CompileSwiftPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/swift/CompileSwiftPhase.kt @@ -4,9 +4,8 @@ import co.touchlab.skie.configuration.SkieConfigurationFlag import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.sir.element.SirCompilableFile import co.touchlab.skie.util.Command +import co.touchlab.skie.util.SwiftCompilerConfiguration.BuildType import org.jetbrains.kotlin.backend.konan.BitcodeEmbedding -import org.jetbrains.kotlin.backend.konan.KonanConfigKeys -import org.jetbrains.kotlin.konan.target.platformName import org.jetbrains.kotlin.konan.target.withOSVersion import java.io.File @@ -16,19 +15,16 @@ class CompileSwiftPhase( private val framework = context.framework private val cacheableKotlinFramework = context.cacheableKotlinFramework - private val konanConfig = context.konanConfig private val swiftCompilerConfiguration = context.swiftCompilerConfiguration private val rootConfiguration = context.rootConfiguration - private val configurables = context.configurables private val skieBuildDirectory = context.skieBuildDirectory - private val targetTriple = context.configurables.targetTriple private val swiftFrameworkHeader = context.skieBuildDirectory.swiftCompiler.moduleHeader(framework.moduleName) private val swiftFileList = context.skieBuildDirectory.swiftCompiler.config.swiftFileList(framework.moduleName) private val outputFileMap = context.skieBuildDirectory.swiftCompiler.config.outputFileMap private val objectFiles = skieBuildDirectory.swiftCompiler.objectFiles private val moduleDirectory = skieBuildDirectory.swiftCompiler.module + private val targetTriple = swiftCompilerConfiguration.targetTriple - private val isDebug = konanConfig.debug private val isLibraryEvolutionEnabled = SkieConfigurationFlag.Build_SwiftLibraryEvolution in rootConfiguration.enabledFlags private val isParallelSwiftCompilationEnabled = SkieConfigurationFlag.Build_ParallelSwiftCompilation in rootConfiguration.enabledFlags private val isConcurrentSkieCompilationEnabled = SkieConfigurationFlag.Build_ConcurrentSkieCompilation in rootConfiguration.enabledFlags @@ -51,8 +47,6 @@ class CompileSwiftPhase( copySwiftModuleFiles() copySwiftLibraryEvolutionFiles() - - addSwiftSpecificLinkerArgs() } private fun createSwiftFileList(sourceFiles: List) { @@ -62,7 +56,7 @@ class CompileSwiftPhase( } private fun createOutputFileMap(sourceFiles: List) { - if (!isDebug) { + if (swiftCompilerConfiguration.buildType != BuildType.Debug) { return } @@ -92,7 +86,7 @@ class CompileSwiftPhase( } private fun callSwiftCompiler() { - Command("${configurables.absoluteTargetToolchain}/usr/bin/swiftc").apply { + Command("${swiftCompilerConfiguration.absoluteTargetToolchainPath}/usr/bin/swiftc").apply { +listOf("-module-name", framework.moduleName) +"-import-underlying-module" +"-F" @@ -117,14 +111,17 @@ class CompileSwiftPhase( +"-emit-object" +"-parse-as-library" +"-enable-batch-mode" - if (isDebug) { - +"-Onone" - +"-incremental" - +"-output-file-map" - +outputFileMap.absolutePath - } else { - +"-O" - +"-whole-module-optimization" + when (swiftCompilerConfiguration.buildType) { + BuildType.Debug -> { + +"-Onone" + +"-incremental" + +"-output-file-map" + +outputFileMap.absolutePath + } + BuildType.Release -> { + +"-O" + +"-whole-module-optimization" + } } +"-g" +"-module-cache-path" @@ -133,9 +130,10 @@ class CompileSwiftPhase( +swiftCompilerConfiguration.swiftVersion +parallelizationArgument +"-sdk" - +configurables.absoluteTargetSysRoot + +swiftCompilerConfiguration.absoluteTargetSysRootPath +"-target" - +configurables.targetTriple.withOSVersion(configurables.osVersionMin).toString() + +swiftCompilerConfiguration.targetTriple.withOSVersion(swiftCompilerConfiguration.osVersionMin).toString() + +swiftCompilerConfiguration.additionalFlags +"@${swiftFileList.absolutePath}" workingDirectory = objectFiles.directory @@ -145,26 +143,29 @@ class CompileSwiftPhase( } private fun deleteOldObjectFiles(sourceFiles: List) { - if (isDebug) { - val sourceFilesNames = sourceFiles.map { it.nameWithoutExtension }.toSet() - - objectFiles.allFiles - .filterNot { it.nameWithoutExtension in sourceFilesNames } - .forEach { - it.delete() - } - } else { - objectFiles.allFiles - .filter { it.nameWithoutExtension != framework.moduleName } - .forEach { - it.delete() - } + when (swiftCompilerConfiguration.buildType) { + BuildType.Debug -> { + val sourceFilesNames = sourceFiles.map { it.nameWithoutExtension }.toSet() + + objectFiles.allFiles + .filterNot { it.nameWithoutExtension in sourceFilesNames } + .forEach { + it.delete() + } + } + BuildType.Release -> { + objectFiles.allFiles + .filter { it.nameWithoutExtension != framework.moduleName } + .forEach { + it.delete() + } + } } } private fun getSwiftcBitcodeArg() = - when (konanConfig.configuration.get(KonanConfigKeys.BITCODE_EMBEDDING_MODE)) { - BitcodeEmbedding.Mode.NONE, null -> null + when (swiftCompilerConfiguration.bitcodeEmbeddingMode) { + BitcodeEmbedding.Mode.NONE -> null BitcodeEmbedding.Mode.FULL -> "-embed-bitcode" BitcodeEmbedding.Mode.MARKER -> "-embed-bitcode-marker" } @@ -188,25 +189,12 @@ class CompileSwiftPhase( swiftFrameworkHeader.swiftInterface.copyTo(framework.swiftInterface(targetTriple), overwrite = true) swiftFrameworkHeader.privateSwiftInterface.copyTo(framework.privateSwiftInterface(targetTriple), overwrite = true) } else { + // WIP Check what happens with swiftFrameworkHeader framework.swiftInterface(targetTriple).delete() framework.privateSwiftInterface(targetTriple).delete() } } - private fun addSwiftSpecificLinkerArgs() { - val swiftLibSearchPaths = listOf( - File(configurables.absoluteTargetToolchain, "usr/lib/swift/${configurables.platformName().lowercase()}"), - File(configurables.absoluteTargetSysRoot, "usr/lib/swift"), - ).flatMap { listOf("-L", it.absolutePath) } - - val otherLinkerFlags = listOf( - "-rpath", "/usr/lib/swift", "-dead_strip", - ) - - konanConfig.configuration.addAll(KonanConfigKeys.LINKER_ARGS, swiftLibSearchPaths) - konanConfig.configuration.addAll(KonanConfigKeys.LINKER_ARGS, otherLinkerFlags) - } - private val parallelizationArgument: String get() { val numberOfAvailableProcessors = if (isParallelSwiftCompilationEnabled) { diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/swift/SwiftCompilerConfiguration.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/swift/SwiftCompilerConfiguration.kt deleted file mode 100644 index c649cf837..000000000 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/swift/SwiftCompilerConfiguration.kt +++ /dev/null @@ -1,10 +0,0 @@ -package co.touchlab.skie.phases.swift - -import java.io.File - -// TODO Unify with SkieConfiguration -data class SwiftCompilerConfiguration( - val sourceFilesDirectory: File, - val swiftVersion: String, - val additionalFlags: List, -) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/typeconflicts/RenameTypesConflictsWithOtherTypesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/typeconflicts/RenameTypesConflictsWithOtherTypesPhase.kt index 634f1aa51..2b814c603 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/typeconflicts/RenameTypesConflictsWithOtherTypesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/typeconflicts/RenameTypesConflictsWithOtherTypesPhase.kt @@ -11,8 +11,6 @@ import co.touchlab.skie.sir.element.isRemoved import co.touchlab.skie.sir.element.oirClassOrNull import co.touchlab.skie.sir.element.resolveAsKirClass import co.touchlab.skie.util.resolveCollisionWithWarning -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe object RenameTypesConflictsWithOtherTypesPhase : SirPhase { @@ -30,7 +28,6 @@ object RenameTypesConflictsWithOtherTypesPhase : SirPhase { * classes are prioritized over type aliases * originating from Kotlin (is prioritized) * Kotlin class vs file (class is prioritized) - * Kotlin class nesting level if available (lower is prioritized) * Kotlin fqName if available * Kotlin SirClasses with shorter Obj-C names are prioritized */ @@ -52,28 +49,12 @@ object RenameTypesConflictsWithOtherTypesPhase : SirPhase { .thenByDescending { it is SirClass } .thenByDescending { it.resolveAsKirClass() != null } .thenByDescending { it.resolveAsKirClass()?.kind != KirClass.Kind.File } - .thenBy { it.resolveAsKirClass()?.kotlinClassNestingLevel ?: 0 } - .thenBy { it.resolveAsKirClass()?.kotlinName ?: "" } + .thenBy { it.resolveAsKirClass()?.kotlinFqName ?: "" } .thenBy { it.getOirClassOrNull()?.name?.length ?: Int.MAX_VALUE } private val SirFqName.depth: Int get() = 1 + (this.parent?.depth ?: 0) - private val KirClass.kotlinName: String - get() = when (val descriptor = this.descriptor) { - is KirClass.Descriptor.Class -> descriptor.value.fqNameSafe.asString() - is KirClass.Descriptor.File -> descriptor.value.name ?: "" - } - - private val KirClass.kotlinClassNestingLevel: Int - get() = when (val descriptor = this.descriptor) { - is KirClass.Descriptor.Class -> descriptor.value.kotlinClassNestingLevel - is KirClass.Descriptor.File -> 0 - } - - private val ClassDescriptor.kotlinClassNestingLevel: Int - get() = 1 + ((this.containingDeclaration as? ClassDescriptor)?.kotlinClassNestingLevel ?: 0) - private fun SirTypeDeclaration.getOirClassOrNull(): OirClass? = (this as? SirClass)?.oirClassOrNull diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/typeconflicts/TemporarilyRenameTypesConflictingWithExternalModulesPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/typeconflicts/TemporarilyRenameTypesConflictingWithExternalModulesPhase.kt index b899c908b..e8299c6e8 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/typeconflicts/TemporarilyRenameTypesConflictingWithExternalModulesPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/typeconflicts/TemporarilyRenameTypesConflictingWithExternalModulesPhase.kt @@ -7,6 +7,7 @@ import co.touchlab.skie.sir.element.SirTypeDeclaration import co.touchlab.skie.sir.element.module // Needed for ApiNotes used for the Swift files compilation but not for the final ApiNotes in the framework +// Allows us to not rename types that conflict with external modules // Must be the last phase that renames SirTypeDeclarations object TemporarilyRenameTypesConflictingWithExternalModulesPhase : SirPhase { diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/SkiePhaseGroup.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/SkiePhaseGroup.kt index e3760aac5..ed4b31a9a 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/SkiePhaseGroup.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/SkiePhaseGroup.kt @@ -1,11 +1,13 @@ package co.touchlab.skie.phases.util import co.touchlab.skie.configuration.SkieConfigurationFlag -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.BackgroundPhase +import co.touchlab.skie.phases.ForegroundPhase +import co.touchlab.skie.phases.ScheduledPhase import kotlinx.coroutines.runBlocking import kotlin.reflect.KClass -class SkiePhaseGroup

, C : SkiePhase.Context>( +class SkiePhaseGroup

, C : ScheduledPhase.Context>( defaultPhasesBuilder: MutableList

.(C) -> Unit, ) { @@ -15,52 +17,8 @@ class SkiePhaseGroup

, C : SkiePhase.Context>( modifications.add(modification) } - context(SkiePhase.Context) - inline fun run(noinline contextFactory: () -> RC): RC = - run(RC::class, contextFactory) - - context(SkiePhase.Context) - fun run(contextClass: KClass, contextFactory: () -> RC): RC = - runBlocking { - prepareAndExecute(contextClass, contextFactory) - } - - context(SkiePhase.Context) - inline fun launch(noinline contextFactory: () -> RC) = - launch(RC::class, contextFactory) - - context(SkiePhase.Context) - fun launch(contextClass: KClass, contextFactory: () -> RC) { - if (SkieConfigurationFlag.Build_ConcurrentSkieCompilation.isEnabled) { - this@Context.launch { - prepareAndExecute(contextClass, contextFactory) - } - } else { - run(contextClass, contextFactory) - } - } - - context(SkiePhase.Context) - private suspend fun prepareAndExecute(contextClass: KClass, contextFactory: () -> RC): RC { - val phasesName = contextClass.nameForLogger.removeSuffix("Phase.Context") + "Phases" - - val (context, phases) = skiePerformanceAnalyticsProducer.log("Initialize$phasesName") { - val context = contextFactory() - - val phases = buildPhases(context) - - context to phases - } - - with(context) { - phases.execute() - } - - return context - } - context(C) - private suspend fun List

.execute() { + internal suspend fun List

.execute() { this.forEach { if (it.isActive()) { context.skiePerformanceAnalyticsProducer.log(it::class.nameForLogger) { @@ -72,7 +30,7 @@ class SkiePhaseGroup

, C : SkiePhase.Context>( } } - private fun buildPhases(context: C): List

{ + internal fun buildPhases(context: C): List

{ val phases = mutableListOf

() modifications.forEach { modification -> @@ -90,3 +48,65 @@ private val KClass<*>.nameForLogger: String ?.joinToString(".") ?.takeUnless { it.isBlank() } ?: "" + +context(ScheduledPhase.Context) +inline fun SkiePhaseGroup.run( + noinline contextFactory: () -> C, +) where P : ScheduledPhase, P : BackgroundPhase { + run(C::class, contextFactory) +} + +context(ScheduledPhase.Context) +fun SkiePhaseGroup.run( + contextClass: KClass, + contextFactory: () -> C, +) where P : ScheduledPhase, P : BackgroundPhase { + if (SkieConfigurationFlag.Build_ConcurrentSkieCompilation.isEnabled) { + this@Context.launch { + prepareAndExecute(contextClass, contextFactory) + } + } else { + runBlocking(contextClass, contextFactory) + } +} + +context(ScheduledPhase.Context) +inline fun SkiePhaseGroup.run( + noinline contextFactory: () -> C, +): C where P : ScheduledPhase, P : ForegroundPhase = + run(C::class, contextFactory) + +context(ScheduledPhase.Context) +fun SkiePhaseGroup.run( + contextClass: KClass, + contextFactory: () -> C, +): C where P : ScheduledPhase, P : ForegroundPhase = + runBlocking(contextClass, contextFactory) + +context(ScheduledPhase.Context) +private fun

, C : ScheduledPhase.Context> SkiePhaseGroup.runBlocking(contextClass: KClass, contextFactory: () -> C): C = + runBlocking { + prepareAndExecute(contextClass, contextFactory) + } + +context(ScheduledPhase.Context) +private suspend fun

, C : ScheduledPhase.Context> SkiePhaseGroup.prepareAndExecute( + contextClass: KClass, + contextFactory: () -> C, +): C { + val phasesName = contextClass.nameForLogger.removeSuffix("Phase.Context") + "Phases" + + val (context, phases) = skiePerformanceAnalyticsProducer.log("Initialize$phasesName") { + val context = contextFactory() + + val phases = buildPhases(context) + + context to phases + } + + with(context) { + phases.execute() + } + + return context +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulDescriptorConversionPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulDescriptorConversionPhase.kt new file mode 100644 index 000000000..94b5c1eb6 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulDescriptorConversionPhase.kt @@ -0,0 +1,5 @@ +package co.touchlab.skie.phases.util + +import co.touchlab.skie.phases.DescriptorConversionPhase + +abstract class StatefulDescriptorConversionPhase : DescriptorConversionPhase, StatefulScheduledPhase() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulScheduledPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulScheduledPhase.kt new file mode 100644 index 000000000..1e234fdbc --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulScheduledPhase.kt @@ -0,0 +1,20 @@ +package co.touchlab.skie.phases.util + +import co.touchlab.skie.phases.ScheduledPhase + +abstract class StatefulScheduledPhase : ScheduledPhase { + + context(C) + override suspend fun execute() { + // Cannot be in the init because the object instance is not available yet. + check(this::class.objectInstance != null) { + "StatefulScheduledPhase ${this::class.qualifiedName} must be an object." + } + + executeStatefulScheduledPhase(this, this@C) + } +} + +fun , C : ScheduledPhase.Context> ScheduledPhase.Context.doInPhase(phase: T, action: C.() -> Unit) { + storeStatefulScheduledPhaseBody(phase, action) +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulSirPhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulSirPhase.kt index 35d2eed01..d11414d35 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulSirPhase.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulSirPhase.kt @@ -2,4 +2,4 @@ package co.touchlab.skie.phases.util import co.touchlab.skie.phases.SirPhase -abstract class StatefulSirPhase : SirPhase, StatefulSkiePhase() +abstract class StatefulSirPhase : SirPhase, StatefulScheduledPhase() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulSkiePhase.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulSkiePhase.kt deleted file mode 100644 index 7c2f458cd..000000000 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/phases/util/StatefulSkiePhase.kt +++ /dev/null @@ -1,42 +0,0 @@ -package co.touchlab.skie.phases.util - -import co.touchlab.skie.phases.SkiePhase -import org.jetbrains.kotlin.config.CompilerConfigurationKey - -// Final implementation must be an object -abstract class StatefulSkiePhase : SkiePhase { - - internal val key = - object : CompilerConfigurationKey Unit>>("StatefulSkiePhase(${this::class.qualifiedName}) actions") {} - - context(C) - override suspend fun execute() { - val state = context.getOrNull(key) ?: StateHolder() - - state.forEach { - it(this@C) - } - } - - // Wrapper class avoids problem with configuration automatically returning immutable copy of the list - internal class StateHolder { - - private val actions = mutableListOf() - - fun add(action: STATE) { - actions.add(action) - } - - fun forEach(action: (STATE) -> Unit) { - actions.forEach(action) - } - } -} - -fun , C : SkiePhase.Context> SkiePhase.Context.doInPhase(phase: T, action: C.() -> Unit) { - val stateHolder = getOrCreate(phase.key) { - StatefulSkiePhase.StateHolder() - } - - stateHolder.add(action) -} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/ClassNamespaceProvider.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/ClassNamespaceProvider.kt index 477fa69f0..33c0b79e5 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/ClassNamespaceProvider.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/ClassNamespaceProvider.kt @@ -4,18 +4,17 @@ import co.touchlab.skie.kir.KirProvider import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.kir.element.KirClassParent import co.touchlab.skie.kir.element.KirModule -import co.touchlab.skie.kir.element.classDescriptorOrNull +import co.touchlab.skie.oir.OirProvider import co.touchlab.skie.sir.element.SirClass import co.touchlab.skie.sir.element.SirExtension import co.touchlab.skie.sir.element.SirIrFile import co.touchlab.skie.sir.element.SirTypeAlias import co.touchlab.skie.util.swift.toValidSwiftIdentifier -import org.jetbrains.kotlin.descriptors.ModuleDescriptor class ClassNamespaceProvider( - private val kirProvider: KirProvider, + kirProvider: KirProvider, + private val oirProvider: OirProvider, private val sirProvider: SirProvider, - private val mainModuleDescriptor: ModuleDescriptor, ) { private val namespaceClassCache = mutableMapOf() @@ -23,7 +22,7 @@ class ClassNamespaceProvider( private val moduleNamespaceCache = mutableMapOf() private val classNamespaceFile by lazy { - sirProvider.fileProvider.getIrFile(kirProvider.skieModule.name, "Namespace") + sirProvider.fileProvider.getIrFile(oirProvider.skieModule.name, "Namespace") } private val classNamespaceBaseClass: SirClass by lazy { @@ -34,8 +33,8 @@ class ClassNamespaceProvider( ) } - private val modulesWithShortNameCollision = - kirProvider.allModules + private val kotlinModulesWithShortNameCollision = + kirProvider.kotlinModules .groupBy { it.shortNamespaceModuleName } .filter { it.value.size > 1 } .values @@ -95,16 +94,19 @@ class ClassNamespaceProvider( private val KirClass.skieFileNamespaceName: String get() { - val isProducedBySkie = this.belongsToSkieKotlinRuntime || this.module.descriptor == mainModuleDescriptor + val isProducedBySkie = when (this.module.origin) { + KirModule.Origin.SkieRuntime, KirModule.Origin.SkieGenerated -> true + KirModule.Origin.Kotlin, KirModule.Origin.External -> false + } - return if (isProducedBySkie) kirProvider.skieModule.name else module.namespaceModuleName + return if (isProducedBySkie) oirProvider.skieModule.name else module.namespaceModuleName } private val KirModule.shortNameCollides: Boolean - get() = this in modulesWithShortNameCollision + get() = this in kotlinModulesWithShortNameCollision private val KirClass.classNamespaceSimpleName: String - get() = this.classDescriptorOrNull?.name?.identifier?.toValidSwiftIdentifier() ?: this.name.swiftName + get() = this.kotlinIdentifier.toValidSwiftIdentifier() @Suppress("RecursivePropertyAccessor") private val KirClass.skieFileName: String diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/SirFileProvider.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/SirFileProvider.kt index 920a6324a..fd472291e 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/SirFileProvider.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/SirFileProvider.kt @@ -1,6 +1,6 @@ package co.touchlab.skie.sir -import co.touchlab.skie.kir.KirProvider +import co.touchlab.skie.oir.OirProvider import co.touchlab.skie.sir.element.SirCompilableFile import co.touchlab.skie.sir.element.SirIrFile import co.touchlab.skie.sir.element.SirModule @@ -14,7 +14,7 @@ import kotlin.io.path.extension class SirFileProvider( private val skieModule: SirModule.Skie, - private val kirProvider: KirProvider, + private val oirProvider: OirProvider, private val skieBuildDirectory: SkieBuildDirectory, ) { @@ -25,7 +25,7 @@ class SirFileProvider( private val generatedSourceFileByPathCache = mutableMapOf() private val skieNamespace: String - get() = kirProvider.skieModule.name + get() = oirProvider.skieModule.name fun getWrittenSourceFileFromSkieNamespace(name: String): SirSourceFile { val path = relativePath(skieNamespace, name) diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/SirProvider.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/SirProvider.kt index cddf55a27..d24ffb9a3 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/SirProvider.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/SirProvider.kt @@ -2,11 +2,8 @@ package co.touchlab.skie.sir import co.touchlab.skie.configuration.ClassInterop import co.touchlab.skie.configuration.RootConfiguration -import co.touchlab.skie.configuration.provider.descriptor.DescriptorConfigurationProvider -import co.touchlab.skie.kir.KirProvider +import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.oir.OirProvider -import co.touchlab.skie.oir.element.OirClass -import co.touchlab.skie.oir.element.cinteropClassDescriptorOrNull import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.sir.builtin.SirBuiltins import co.touchlab.skie.sir.element.SirCallableDeclaration @@ -26,18 +23,16 @@ import co.touchlab.skie.util.directory.SkieBuildDirectory class SirProvider( framework: FrameworkLayout, - kirProvider: KirProvider, private val oirProvider: OirProvider, - private val descriptorConfigurationProvider: DescriptorConfigurationProvider, - rootConfiguration: RootConfiguration, skieBuildDirectory: SkieBuildDirectory, + rootConfiguration: RootConfiguration, ) { val kotlinModule: SirModule.Kotlin = SirModule.Kotlin(framework.moduleName) val skieModule: SirModule.Skie = SirModule.Skie(framework.moduleName) - val fileProvider: SirFileProvider = SirFileProvider(skieModule, kirProvider, skieBuildDirectory) + val fileProvider: SirFileProvider = SirFileProvider(skieModule, oirProvider, skieBuildDirectory) val sirBuiltins by lazy { SirBuiltins(this, rootConfiguration) @@ -63,7 +58,7 @@ class SirProvider( get() = allLocalClasses.filter { it.kind == SirClass.Kind.Enum } val allUsedExternalModules: List - get() = oirProvider.allExternalClassesAndProtocols + get() = oirProvider.externalClassesAndProtocols .map { it.originalSirClass.module } .filterIsInstance() .distinct() @@ -121,13 +116,14 @@ class SirProvider( } fun getClassByFqName(fqName: SirFqName): SirClass = - findClassByFqName(fqName) - ?: error("SirClass with fqName $fqName not found.") + findClassByFqName(fqName) ?: error("SirClass with fqName $fqName not found.") - fun findExternalModule(oirClass: OirClass): SirModule.External? { - val classDescriptor = oirClass.cinteropClassDescriptorOrNull ?: error("Invalid origin for OirClass: $oirClass") + fun findExternalModule(kirClass: KirClass): SirModule.External? { + if (kirClass.origin == KirClass.Origin.Kotlin) { + error("KirClass is not external: $kirClass") + } - val moduleName = descriptorConfigurationProvider.getConfiguration(classDescriptor)[ClassInterop.CInteropFrameworkName] ?: return null + val moduleName = kirClass.configuration[ClassInterop.CInteropFrameworkName] ?: return null return getExternalModule(moduleName) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/type/SirDeclaredSirType.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/type/SirDeclaredSirType.kt index f8b4398c8..28f62e6d8 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/type/SirDeclaredSirType.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/sir/type/SirDeclaredSirType.kt @@ -1,6 +1,5 @@ package co.touchlab.skie.sir.type -import co.touchlab.skie.oir.element.cinteropClassDescriptorOrNull import co.touchlab.skie.sir.SirFqName import co.touchlab.skie.sir.element.SirClass import co.touchlab.skie.sir.element.SirModule @@ -8,12 +7,10 @@ import co.touchlab.skie.sir.element.SirTypeAlias import co.touchlab.skie.sir.element.SirTypeDeclaration import co.touchlab.skie.sir.element.SirTypeParameter import co.touchlab.skie.sir.element.module -import co.touchlab.skie.sir.element.oirClassOrNull -import co.touchlab.skie.sir.element.resolveAsSirClass +import co.touchlab.skie.sir.element.resolveAsKirClass import io.outfoxx.swiftpoet.DeclaredTypeName import io.outfoxx.swiftpoet.TypeName import io.outfoxx.swiftpoet.parameterizedBy -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe data class SirDeclaredSirType( val declaration: SirTypeDeclaration, @@ -64,11 +61,7 @@ data class SirDeclaredSirType( } private fun getUnknownCInteropModuleType(): SkieErrorSirType.UnknownCInteropFramework { - val oirClass = declaration.resolveAsSirClass()?.oirClassOrNull - - val classDescriptor = oirClass?.cinteropClassDescriptorOrNull - - val name = classDescriptor?.fqNameSafe?.asString() ?: declaration.fqName.toLocalString() + val name = declaration.resolveAsKirClass()?.kotlinFqName ?: declaration.fqName.toLocalString() return SkieErrorSirType.UnknownCInteropFramework(name) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/Reporter.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/Reporter.kt index 07017f396..e45e71217 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/Reporter.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/Reporter.kt @@ -1,41 +1,29 @@ package co.touchlab.skie.util -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.MessageUtil -import org.jetbrains.kotlin.cli.jvm.compiler.report -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi -import org.jetbrains.kotlin.renderer.DescriptorRenderer - -class Reporter(private val compilerConfiguration: CompilerConfiguration) { - - fun report(severity: Severity, message: String, declaration: DeclarationDescriptor? = null) { - val location = MessageUtil.psiElementToMessageLocation(declaration?.findPsi())?.let { - CompilerMessageLocation.create(it.path, it.line, it.column, it.lineContent) - } - - if (declaration != null && location == null) { - return report(severity, "$message\n (at ${DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(declaration)})", null) - } - - when (severity) { - Severity.Error -> compilerConfiguration.report(CompilerMessageSeverity.ERROR, message, location) - Severity.Warning -> compilerConfiguration.report(CompilerMessageSeverity.WARNING, message, location) - Severity.None -> {} - } +import co.touchlab.skie.kir.element.KirElement +import java.util.Collections + +class Reporter { + + private val mutableReports = Collections.synchronizedList(mutableListOf()) + + val reports: List by ::mutableReports + + fun report(severity: Severity, message: String, source: KirElement? = null) { + mutableReports.add(Report(message, severity, source)) } - fun error(message: String, declaration: DeclarationDescriptor? = null) { - report(Severity.Error, message, declaration) + fun error(message: String, source: KirElement? = null) { + report(Severity.Error, message, source) } - fun warning(message: String, declaration: DeclarationDescriptor? = null) { - report(Severity.Warning, message, declaration) + fun warning(message: String, source: KirElement? = null) { + report(Severity.Warning, message, source) } enum class Severity { - Error, Warning, None + Error, Warning } + + data class Report(val message: String, val severity: Severity, val source: KirElement?) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/SirDeclaration+resolveCollision.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/SirDeclaration+resolveCollision.kt index fc7027175..7c4009771 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/SirDeclaration+resolveCollision.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/SirDeclaration+resolveCollision.kt @@ -7,7 +7,6 @@ import co.touchlab.skie.kir.element.KirCallableDeclaration import co.touchlab.skie.kir.element.KirClass import co.touchlab.skie.kir.element.KirElement import co.touchlab.skie.kir.element.KirEnumEntry -import co.touchlab.skie.kir.element.classDescriptorOrNull import co.touchlab.skie.phases.SirPhase import co.touchlab.skie.sir.element.SirCallableDeclaration import co.touchlab.skie.sir.element.SirConstructor @@ -17,7 +16,6 @@ import co.touchlab.skie.sir.element.SirSimpleFunction import co.touchlab.skie.sir.element.SirTypeDeclaration import co.touchlab.skie.sir.element.kirClassOrNull import co.touchlab.skie.sir.element.resolveAsKirClass -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor context(SirPhase.Context) fun T.resolveCollisionWithWarning(collisionReasonProvider: T.() -> String?): Boolean = @@ -61,7 +59,6 @@ fun SirEnumCase.resolveCollisionWithWarning(collisionReasonProvider: SirEnumCase rename = { simpleName += "_" }, getName = { toReadableString() }, findKirElement = { parent.kirClassOrNull?.enumEntries?.get(index) }, - getDescriptor = { descriptor }, ) context(SirPhase.Context) @@ -77,13 +74,6 @@ private inline fun T.resolveCollisionWithWarning( kirProvider.findCallableDeclaration(this) ?: if (this is SirProperty) kirProvider.findEnumEntry(this) else null }, - getDescriptor = { - when (this) { - is KirCallableDeclaration<*> -> descriptor - is KirEnumEntry -> descriptor - else -> null - } - }, ) context(SirPhase.Context) @@ -96,7 +86,6 @@ private inline fun T.resolveCollisionWithWarning( rename = rename, getName = { toReadableString() }, findKirElement = { resolveAsKirClass() }, - getDescriptor = { classDescriptorOrNull }, ) context(SirPhase.Context) @@ -105,7 +94,6 @@ private inline fun T.resolveCollisionWithWarning( rename: () -> Unit, getName: T.() -> String, findKirElement: T.() -> K?, - getDescriptor: K.() -> DeclarationDescriptor?, ): Boolean { val collisionReason = collisionReasonProvider() ?: return false @@ -121,7 +109,7 @@ private inline fun T.resolveCollisionWithWarning( originalName = originalName, newName = newName, collisionReason = collisionReason, - declarationDescriptor = kirElement.getDescriptor(), + source = kirElement, ) } @@ -148,13 +136,13 @@ private fun reportCollision( originalName: String, newName: String, collisionReason: String, - declarationDescriptor: DeclarationDescriptor?, + source: KirElement, ) { reporter.warning( message = "'$originalName' was renamed to '$newName' because of a name collision with $collisionReason. " + "Consider resolving the conflict either by changing the name in Kotlin, or via the @ObjCName annotation. " + "You can also suppress this warning using the 'SuppressSkieWarning.NameCollision' configuration. " + "However using renamed declarations from Swift is not recommended because their name will change if the conflict is resolved.", - declaration = declarationDescriptor, + source = source, ) } diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/SwiftCompilerConfiguration.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/SwiftCompilerConfiguration.kt new file mode 100644 index 000000000..2e7a21312 --- /dev/null +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/SwiftCompilerConfiguration.kt @@ -0,0 +1,20 @@ +package co.touchlab.skie.util + +import org.jetbrains.kotlin.backend.konan.BitcodeEmbedding +import org.jetbrains.kotlin.konan.target.TargetTriple + +data class SwiftCompilerConfiguration( + val swiftVersion: String, + val additionalFlags: List, + val buildType: BuildType, + val targetTriple: TargetTriple, + val bitcodeEmbeddingMode: BitcodeEmbedding.Mode, + val absoluteTargetToolchainPath: String, + val absoluteTargetSysRootPath: String, + val osVersionMin: String, +) { + + enum class BuildType { + Debug, Release + } +} diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/parallel/ParallelFlatMap.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/parallel/ParallelFlatMap.kt index 2a0accf7b..bbcf42bf9 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/parallel/ParallelFlatMap.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/parallel/ParallelFlatMap.kt @@ -1,7 +1,7 @@ package co.touchlab.skie.util.parallel -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.ScheduledPhase -context(SkiePhase.Context) +context(ScheduledPhase.Context) suspend fun Collection.parallelFlatMap(optimalChunkSize: Int = 100, transform: suspend (T) -> Iterable): List = parallelMap(optimalChunkSize, transform).flatten() diff --git a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/parallel/ParallelMap.kt b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/parallel/ParallelMap.kt index 114da3692..24cdb7d88 100644 --- a/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/parallel/ParallelMap.kt +++ b/SKIE/compiler/kotlin-plugin/src/kgp_common/kotlin/co/touchlab/skie/util/parallel/ParallelMap.kt @@ -1,14 +1,14 @@ package co.touchlab.skie.util.parallel import co.touchlab.skie.configuration.SkieConfigurationFlag -import co.touchlab.skie.phases.SkiePhase +import co.touchlab.skie.phases.ScheduledPhase import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.withContext -context(SkiePhase.Context) +context(ScheduledPhase.Context) suspend fun Collection.parallelMap(optimalChunkSize: Int = 100, transform: suspend (T) -> R): List { if (SkieConfigurationFlag.Build_ParallelSkieCompilation.isDisabled) { return map { transform(it) }