Macros in Swift vs. KSP in Kotlin

๐Ÿ‘
· Jan 10, 2023 · 4 mins read
Macros in Swift vs. KSP in Kotlin

Preface

In essence, these two technologies are completely different. While one is generating code by expanding the macro patterns, another is generating code freely based on the meta data stored in the complied code.

However, Swift macro is not like the regular macro we know in many languages, where it is mainly a string manipulation. Instead, the macro expansion in Swift embraces AST, which makes its way of working similar to KSP. Since these are two important ways of generating code for mobile apps(iOS & Android), letโ€™s compare them so that we can better utilise them.

Follow me if you are interested in topics like this.

What is Macro in Swift

In Swift, there are a lot of ways compiler can generate code. For example, conforming a struct type to protocols like Codable, Equtableetc., the compiler can potentially generated code needed for these protocols. ResultBuilder allows us to writing declarative code and the Swift compiler do the heavily lifting work by generating necessary code behind the scene. Just to name a few. For more, please refer to the picture below:

https://developer.apple.com/videos/play/wwdc2023/10167/?time=92

Macro is a new addition to this category and it is a big deal. Because not only is itself a very useful feature but it is also an enabler for many awesome features like @Observerble, @Model. Its super power is just like PropertyWrapper in Swift, which makes many great features like @State, @ObservedObject, @Published possible and paves the way for SwiftUI.

In short, Swift compiler expandsMacro based on the macro definition, which is similar to the macro in many languages. However, the design of Swift macros is also unique as it utilises AST instead of pure string manipulation and this makes this feature in Swift shine.

What is KSP in Kotlin

Kotlin Symbol Processing (KSP) is an API that we can use to develop lightweight compiler plugins and is an evolutionary version of their predecessor Kapt. They rely on the information of the Annotations and AST from the compiled code.

What are in common

All about code generation

Both technologies aim to generate code and are great ways to DRY our code.

Both rely on AST

They both rely on AST, which means they are based on the complied code information and not are just string mapping or manipulation.

Both have library to support code generating

In order the help code generating process, we have great libraries for both of them.[SwiftSyntaxBuilder](https://github.com/apple/swift-syntax/tree/main/Sources/SwiftSyntaxBuilder) is for generating Swift code and [KotlinPoet](https://square.github.io/kotlinpoet/) for Kotlin.

What are the differences

What code can be generated

KSP gives us great freedom in terms generating code. We can implement any logic that suits the needs to generate code. For example, I have designed a solution to generate API network layer code based on the endpoint definitions using KSP, which is similar to Swagger generating API code based on API Schema. In my solution, it relies on Endpoint definition in Kotlin code.

Comparatively speaking, Swift macro has a lot of limitation on the generated code because of the way it works. It has strictly two major types as below:

Freestanding macros: expression and declaration

Attached macros: peer, accessor, member, member attribute and conformance

In the following articles, I will go through all types of Swift macros and create some example usage for each of them.

When to generate code

The Swift Macros are expanded in the complication process and the expanded code then is compiled together with the source code we write.

Regarding code generating from KSP, the code we write is compiled first, then the KSP comes in to process the compiled code and generate code. The generated code is combined into source files and compiled at last.

Where the code to be generated

The code generation for macros in Swift is a process of expanding code in places where macros are defined.

KSP usually writes the generated code into new files.

Special features for Swift Macros

The design goals of the Swift Macro are clear and the solution is so elegant that, in Xcode, they can even offer type check , unit test , inline debugging for all the macros, which will be covered in the future articles.

Comments

Sharing is caring!