/kmp-swift-reveal

Gradle plugin that reveal the Swift code that you should expect from a Kotlin iOS module.

Primary LanguageKotlinMIT LicenseMIT

kmp-swift-reveal 🐘

Gradle plugin that reveal the Swift code that you should expect from a Kotlin iOS module.

➡️ gradlew swiftReveal

import kotlin.experimental.ExperimentalObjCName

class ExampleClass {
    fun mySuperFun(): Int = 10
    fun withCallback(myCallback: () -> String) {}
    fun myFunctionReturnMap(): Map<String, String> = mapOf("Example" to "Value")
    
    @OptIn(ExperimentalObjCName::class)
    @ObjCName(swiftName = "mySwiftNameFunction")
    fun withObjcName() {}
}

fun ExampleClass.myExtensionFunction() {}

fun myTopLevelFunction(): String = "Example return string"

Generated Swift representation

class ExampleClass : KotlinBase {
    public init()
    
    open func myFunctionReturnMap() -> [String : String]

    open func mySuperFun() -> Int32

    open func withCallback(myCallback: @escaping () -> String)

    open func mySwiftNameFunction()
}

extension ExampleClass {
    open func myExtensionFunction()
}

class ExampleClassKt : KotlinBase {
    open class func myTopLevelFunction() -> String
}

Roadmap

  • Support generate swift file from binaries configuration of the module.
  • More examples
  • CI usage examples
  • Filter classes and definitions from module dependencies.
  • Validate and support SKIE

Motivation

First motivation: When writing a Kotlin Multiplatform module targeting iOS is usually hard to know what to expect when going to Swift, with the time we can get a little better at this but we usually miss things.

Second motivation: When working with iOS developers it usually much harder for then to predict what is the output of a Kotlin Multiplatform module. This tool can be hooked into the CI pipeline for example to show ahead of time what the iOS developer should expect.

This project aims to fill this unknown gap before going to XCode and implement using new Kotlin Multiplatform code by generating a Swift representation of the output OBJC Header of your module.

How to use

  • Add the plugin to your module build script
plugins {
    ...
    id("dev.srsouza.gradle.kmp-swift-reveal") version "0.1.1"
}
  • Call: gradlew :yourModule:swiftReveal

  • The file should be located by default in build/kmp-swift-reveal/out/module/module.swift

Configuring

swiftReveal {
    directoryForSwiftGeneratedSourceFromModule.set(layout.projectDirectory.dir("swift-reveal")) // default: build/kmp-swift-reveal/out/module/
}

How it works

The project was inspired by usage of Source Kitten in the talk Kotlin/Multiplatform for iOS developers : state & future by Salomon Brys at Kotlin Conf 23.

Basically, the projects creates a Source Kitten Request for a Swift source code and filter the source code with only your module declarations.

Integration example

You can do a bunch of custom integration with the generated file to make it visible to the iOS Developers the changes that are being taking place in the modules that expose code to Swift.

A simple CI example would be this Github Action Jobs

  # Put the Swift generated file to the `GITHUB_OUTPUT` of the Step
  - name: Get Swift Reveal Output
    id: build_swift_reveal_comment
    run: |
      FILE_CONTENT=$(cat example/swift-reveal/module.swift)
      delimiter="$(openssl rand -hex 8)"
      echo "content<<${delimiter}" >> "${GITHUB_OUTPUT}"
      echo "$FILE_CONTENT" >> "${GITHUB_OUTPUT}"
      echo "${delimiter}" >> "${GITHUB_OUTPUT}"
    if: success()
  # Comment the Swift file to the Github PR using 'maintain-one-comment' Action
  - name: Swift Reveal Comment
    uses: actions-cool/maintain-one-comment@v3
    if: success()
    with:
      token: ${{ secrets.GITHUB_TOKEN }}
      body: |
        ## Swift Reveal result
        ```swift
        ${{ steps.build_swift_reveal_comment.outputs.content }}
        ```
      body-include: '<!-- Swift Reveal Comment -->'

You can get the full example Github Action Workflow here.

Thanks

  • @cortinico for the amazing kotlin-gradle-plugin-template
  • @SalomonBrys for the Kotlin Conf talk that inspired this project
  • Source kitten contributors
  • Kotlin Gradle Plugin and Compose Multiplatform developers for a bunch of Gradle Extensions.