Skip to content

Language Swift

Oliver Atkinson edited this page May 31, 2026 · 1 revision

Swift

Lexicon has two Swift generator targets:

  • swift emits source that imports SwiftLexicon.
  • swift-standalone emits a self-contained Swift file.

Use swift for Swift applications that want the shared runtime, generated event values, and integration with SwiftLexicon. Use swift-standalone when you want a generated vocabulary file with no runtime dependency.

Generate Runtime-Backed Swift

swift run lexicon-generate commerce.lexicon --type swift -o Sources/Generated/Commerce

This writes Sources/Generated/Commerce.swift.

Generated source starts with:

@_exported import SwiftLexicon
import Foundation

public let commerce = L_commerce("commerce")

You can then use dot-path accessors:

import SwiftLexicon

let submit = commerce.api.order.submit
let button = commerce.ui.checkout.button.primary

print(submit.__)
print(button.__)

The __ property is the exact lemma ID.

Generate Stand-Alone Swift

swift run lexicon-generate commerce.lexicon --type swift-standalone -o Sources/Generated/CommerceVocabulary

This writes Sources/Generated/CommerceVocabulary.swift. The generated file contains its own I, L, localization, identity, equality, and generated type declarations.

Use this when the target Swift project should not depend on the Lexicon package at runtime.

SwiftPM Build-Tool Plugin

For a Swift package, add Lexicon as a package dependency:

.package(
	url: "https://github.com/ollieatkinson/Lexicon.git",
	branch: "trunk"
)

Then attach the plugin to the target that owns .lexicon files:

.target(
	name: "CommerceVocabulary",
	dependencies: [
		.product(name: "SwiftLexicon", package: "Lexicon")
	],
	plugins: [
		.plugin(name: "SwiftLibraryGeneratorPlugin", package: "Lexicon")
	]
)

The plugin scans the target directory for files ending in .lexicon and generates Swift into SwiftPM's plugin work directory.

For stand-alone generated Swift:

.target(
	name: "CommerceVocabulary",
	plugins: [
		.plugin(name: "SwiftStandAloneGeneratorPlugin", package: "Lexicon")
	]
)

Reserved Words

Generated Swift wraps selector names in backticks when needed:

let type = commerce.`type`

Exact IDs still keep the original spelling:

print(commerce.`type`.__) // commerce.type

Runtime Events

The runtime-backed generator works with SwiftLexicon events:

import SwiftLexicon

let events = Events()

let subscription = commerce.ux.type.action >> events.then { event in
	let value: String = try event[type: String.self]
	print(value)
}

commerce.ui.product.card.buy["birthday_001"] >> events

subscription.cancel()
events.finish()

Use this when a generated lemma should be both a stable vocabulary path and an event key.

Testing Generated Swift

In application tests, assert exact IDs rather than generated class names:

#expect(commerce.api.order.submit.__ == "commerce.api.order.submit")
#expect(commerce.ui.checkout.button.primary.__ == "commerce.ui.checkout.button.primary")

Generated class names are an implementation detail. Dot paths are the semantic contract.

Clone this wiki locally