Section 3/102 menit

3. Jenis-Jenis Swift Macro

3. Jenis-Jenis Swift Macro

Swift Macro dibagi menjadi dua kategori besar: Freestanding dan Attached.

Freestanding Macro (#macroName)

Freestanding macro dipanggil secara independen menggunakan prefix #. Tidak menempel pada deklarasi lain.

3.1 Expression Macro

Menghasilkan sebuah ekspresi (nilai). Bisa digunakan di mana saja ekspresi diizinkan.

swift
@freestanding(expression)
public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(
    module: "MyMacrosMacros", type: "StringifyMacro"
)

// Penggunaan:
let (value, src) = #stringify(42 * 2)  // menghasilkan ekspresi

3.2 Declaration Macro

Menghasilkan satu atau lebih deklarasi baru (fungsi, struct, class, dll). Digunakan di level file atau type body.

swift
@freestanding(declaration, names: named(makeGreeting))
public macro makeGreeting(for name: String) = #externalMacro(
    module: "MyMacrosMacros", type: "MakeGreetingMacro"
)

// Penggunaan — di level file:
#makeGreeting(for: "World")
// Menghasilkan fungsi:
// func greetWorld() -> String { "Hello, World!" }

Attached Macro (@MacroName)

Attached macro menempel pada deklarasi Swift (class, struct, func, property, dll) dan menghasilkan kode tambahan berdasarkan deklarasi tersebut.

3.3 @attached(member) — Tambah Member ke Type

Menambahkan property, fungsi, atau initializer baru ke dalam type.

swift
@attached(member, names: named(init))
public macro AutoInit() = #externalMacro(
    module: "MyMacrosMacros", type: "AutoInitMacro"
)

// Penggunaan:
@AutoInit
struct Point {
    var x: Double
    var y: Double
    // ← macro generate: init(x: Double, y: Double)
}

3.4 @attached(memberAttribute) — Tambah Atribut ke Member

Menambahkan atribut ke setiap member dari type target (misal: menambahkan @Published ke semua property).

swift
@attached(memberAttribute)
public macro AllPublished() = #externalMacro(
    module: "MyMacrosMacros", type: "AllPublishedMacro"
)

// Penggunaan:
@AllPublished
class ViewModel: ObservableObject {
    var name: String = ""  // ← macro tambahkan @Published
    var age: Int = 0       // ← macro tambahkan @Published
}

3.5 @attached(accessor) — Tambah getter/setter ke Property

Mengubah stored property menjadi computed property dengan getter/setter kustom.

swift
@attached(accessor)
public macro UserDefaultsBacked<T>(_ key: String) = #externalMacro(
    module: "MyMacrosMacros", type: "UserDefaultsBackedMacro"
)

// Penggunaan:
struct Settings {
    @UserDefaultsBacked("username")
    var username: String  // ← macro generate getter/setter ke UserDefaults
}

3.6 @attached(conformance) — Tambah Protocol Conformance

Menambahkan konformitas protokol beserta implementasinya ke type.

swift
@attached(conformance)
public macro AutoCodable() = #externalMacro(
    module: "MyMacrosMacros", type: "AutoCodableMacro"
)

// Penggunaan:
@AutoCodable
struct Config {
    var apiKey: String
    var baseURL: URL
    // ← macro generate: Codable conformance dengan custom CodingKeys
}

3.7 @attached(peer) — Generate Peer Declaration

Menghasilkan deklarasi baru yang "sejajar" (peer) dengan deklarasi target — misalnya membuat fungsi async dari fungsi sinkron.

swift
@attached(peer, names: suffixed(Async))
public macro AddAsync() = #externalMacro(
    module: "MyMacrosMacros", type: "AddAsyncMacro"
)

// Penggunaan:
@AddAsync
func fetchUser(id: String, completion: @escaping (User?) -> Void) { ... }
// ← macro generate:
// func fetchUserAsync(id: String) async -> User? { ... }

3.8 @attached(extension) — Generate Extension

Menghasilkan extension pada type (berbeda dengan conformance yang langsung pada deklarasi).

swift
@attached(extension, conformances: CustomStringConvertible, names: named(description))
public macro AutoDescription() = #externalMacro(
    module: "MyMacrosMacros", type: "AutoDescriptionMacro"
)

// Penggunaan:
@AutoDescription
struct Product {
    let name: String
    let price: Double
}
// ← macro generate:
// extension Product: CustomStringConvertible {
//     var description: String { "Product(name: \(name), price: \(price))" }
// }

Ringkasan Jenis Macro

Jenis Sintaks Menghasilkan Posisi Penggunaan
@freestanding(expression) #macro() Ekspresi/nilai Di dalam ekspresi
@freestanding(declaration) #macro() Deklarasi baru Level file/type
@attached(member) @Macro Member baru di type Pada type
@attached(memberAttribute) @Macro Atribut pada member Pada type
@attached(accessor) @Macro getter/setter Pada property
@attached(conformance) @Macro Protocol conformance Pada type
@attached(peer) @Macro Deklarasi sejajar Pada func/property
@attached(extension) @Macro Extension pada type Pada type