Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ buildscript {
mavenCentral()
google()
gradlePluginPortal()

maven("https://jitpack.io")
}

dependencies {
Expand Down
7 changes: 7 additions & 0 deletions check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
#

./gradlew -p kswift-gradle-plugin build &&
./gradlew build syncMultiPlatformLibraryDebugFrameworkIosX64 &&
cd sample/ios-app && set -o pipefail && xcodebuild -scheme ios-app -workspace ios-app.xcworkspace test -destination "platform=iOS Simulator,name=iPhone 12 mini" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO | xcpretty
7 changes: 7 additions & 0 deletions fastcheck.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
#

./gradlew -p kswift-gradle-plugin assemble detekt &&
./gradlew detekt syncMultiPlatformLibraryDebugFrameworkIosX64 &&
cd sample/ios-app && set -o pipefail && xcodebuild -scheme ios-app -workspace ios-app.xcworkspace test -destination "platform=iOS Simulator,name=iPhone 12 mini" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO | xcpretty
3 changes: 3 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ kotlin.native.enableDependencyPropagation=false
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.mpp.enableCompatibilityMetadataVariant=true

#kotlin.native.jvmArgs=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006
kotlin.native.disableCompilerDaemon=true

android.useAndroidX=true

mobile.multiplatform.iosTargetWarning=false
8 changes: 6 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ mokoResourcesVersion = "0.16.2"
kotlinxMetadataKLibVersion = "0.0.1"

kotlinPoetVersion = "1.6.0"
swiftPoetVersion = "1.1.2"
swiftPoetVersion = "1.3.1"

autoServiceVersion = "1.0-rc6"

[libraries]
appCompat = { module = "androidx.appcompat:appcompat", version.ref = "androidAppCompatVersion" }
Expand All @@ -31,7 +33,9 @@ mokoMvvmState = { module = "dev.icerock.moko:mvvm-state" , version.ref = "mokoMv
mokoResources = { module = "dev.icerock.moko:resources" , version.ref = "mokoResourcesVersion" }

kotlinPoet = { module = "com.squareup:kotlinpoet", version.ref = "kotlinPoetVersion" }
swiftPoet = { module = "com.github.icerockdev:swiftpoet", version.ref = "swiftPoetVersion" }
swiftPoet = { module = "io.outfoxx:swiftpoet", version.ref = "swiftPoetVersion" }

autoService = { module = "com.google.auto.service:auto-service", version.ref = "autoServiceVersion" }

#kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin-api", version.ref = "kotlinVersion" }
kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlinVersion" }
Expand Down
4 changes: 2 additions & 2 deletions kswift-build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repositories {

dependencies {
api("dev.icerock:mobile-multiplatform:0.12.0")
api("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21")
api("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31")
api("com.android.tools.build:gradle:4.2.1")
api("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.15.0")
api("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.18.1")
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ detekt {
}

dependencies {
"detektPlugins"("io.gitlab.arturbosch.detekt:detekt-formatting:1.15.0")
"detektPlugins"("io.gitlab.arturbosch.detekt:detekt-formatting:1.18.1")
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,7 @@
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

import org.gradle.api.JavaVersion
import org.gradle.kotlin.dsl.`java-gradle-plugin`
import org.gradle.kotlin.dsl.withType

plugins {
id("org.jetbrains.kotlin.jvm")
id("jvm-convention")
`java-gradle-plugin`
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
withJavadocJar()
withSourcesJar()
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions.jvmTarget = "1.8"
}
22 changes: 22 additions & 0 deletions kswift-build-logic/src/main/kotlin/jvm-convention.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

import org.gradle.api.JavaVersion
import org.gradle.kotlin.dsl.`java-gradle-plugin`
import org.gradle.kotlin.dsl.withType

plugins {
id("org.jetbrains.kotlin.jvm")
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
withJavadocJar()
withSourcesJar()
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions.jvmTarget = "1.8"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

import org.gradle.api.publish.maven.MavenPublication

plugins {
id("publication-convention")
}

publishing.publications.register("mavenJava", MavenPublication::class) {
from(components["java"])
}
7 changes: 7 additions & 0 deletions kswift-build-logic/src/main/kotlin/kapt-convention.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

plugins {
id("kotlin-kapt")
}
25 changes: 25 additions & 0 deletions kswift-compiler-native-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

plugins {
id("jvm-convention")
id("jvm-publication-convention")
id("kapt-convention")
}

group = "dev.icerock.moko"
version = libs.versions.mokoKSwiftVersion.get()

dependencies {
compileOnly("org.jetbrains.kotlin:kotlin-compiler")

compileOnly(libs.autoService)
kapt(libs.autoService)
}

tasks.compileKotlin.configure {
kotlinOptions {
freeCompilerArgs = listOf("-Xjvm-default=all")
}
}
31 changes: 31 additions & 0 deletions kswift-compiler-native-plugin/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

enableFeaturePreview("VERSION_CATALOGS")

rootProject.name = "kswift-compiler-native-plugin"

pluginManagement {
repositories {
mavenCentral()
google()

gradlePluginPortal()
}
}

dependencyResolutionManagement {
repositories {
mavenCentral()
google()
}

versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}

includeBuild("../kswift-build-logic")
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

package dev.icerock.moko.kswift.compiler

import com.google.auto.service.AutoService
import com.intellij.mock.MockProject
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension

@AutoService(ComponentRegistrar::class)
open class FlowGenericsComponentRegistrar : ComponentRegistrar {

override fun registerProjectComponents(
project: MockProject,
configuration: CompilerConfiguration
) {
val messageCollector: MessageCollector =
configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)

IrGenerationExtension.registerExtension(
project,
FlowGenericsIrGenerationExtension(messageCollector)
)
SyntheticResolveExtension.registerExtension(
project,
FlowGenericsSyntheticsExtension(messageCollector)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

package dev.icerock.moko.kswift.compiler

import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.ir.util.properties

class FlowGenericsIrGenerationExtension(
private val log: MessageCollector
) : IrGenerationExtension {
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
val properties: Sequence<IrProperty> = sequence {
moduleFragment.files.forEach { searchGeneratedProperties(it) }
}
properties.forEach { generateForProperty(it, pluginContext) }
}

private suspend fun SequenceScope<IrProperty>.searchGeneratedProperties(
file: IrFile
) {
return file.declarations.forEach { searchGeneratedProperties(it) }
}

private suspend fun SequenceScope<IrProperty>.searchGeneratedProperties(
declaration: IrDeclaration
) {
when (declaration) {
is IrProperty -> yield(declaration)
is IrClass -> searchGeneratedProperties(declaration)
else -> return
}
}

private suspend fun SequenceScope<IrProperty>.searchGeneratedProperties(
clazz: IrClass
) {
clazz.declarations.forEach { searchGeneratedProperties(it) }
}

private fun generateForProperty(
property: IrProperty,
pluginContext: IrPluginContext
) {
if (property.name.identifier.endsWith("Ks").not()) {
return
}

val getter: IrSimpleFunction? = property.getter
if (getter == null) {
log.debug("skip $property - getter is null")
return
}

val parentClass: IrClass? = property.parentClassOrNull
if (parentClass == null) {
log.debug("skip $property - class is null")
return
}

val originalPropertyIdentifier: String = property.name.identifier.removeSuffix("Ks")
val originalProperty: IrProperty? = parentClass.properties.firstOrNull {
it.name.identifier == originalPropertyIdentifier
}
if (originalProperty == null) {
log.debug("skip $property - original not found")
return
}
val originalGetter = originalProperty.getter
if (originalGetter == null) {
log.debug("skip $property - original getter is null")
return
}

getter.body = DeclarationIrBuilder(pluginContext, getter.symbol).irBlockBody {
+irReturn(callOriginalFunction(getter, originalGetter))
}
log.debug("body for ${property.name} added")
}

private fun IrBuilderWithScope.callOriginalFunction(
function: IrFunction,
originalFunction: IrFunction
) = irCall(originalFunction).apply {
dispatchReceiver = function.dispatchReceiverParameter?.let { irGet(it) }
extensionReceiver = function.extensionReceiverParameter?.let { irGet(it) }
passTypeArgumentsFrom(function)
function.valueParameters.forEachIndexed { index, parameter ->
putValueArgument(index, irGet(parameter))
}
}
}
Loading