🚀

Swift Macrosが難しいからスーパーシンプルなマクロ作った

2024/04/29に公開

SUMMARY

Swift Macrosの公式ドキュメントが難しすぎたので、
スーパーシンプルなマクロリポジトリを作ったよってお話です。
本当に簡単な要素しか入れていないので、
Swift-Syntaxよく知らないけど話題のSwift Macrosどんなもんよって方に見てもらえれば幸いです。

https://github.com/MrSmart00/HelloWorldMacro

はじまり

ちょっとしたきっかけがあったので、Swift Macrosやるかーってなったんですが、

状態になった。

頑張ってまとめたのがこのスクラップ

https://zenn.dev/nexearth/scraps/6ee07d7408a7dc

スーパーシンプルなマクロを作ろう

自分にはレベルが高すぎて、文章だけだと理解が追いつかないので、
実際にリポジトリ作ってスーパーシンプルなマクロを作ってみました。

https://github.com/MrSmart00/HelloWorldMacro

文字列を渡すと Hello World を追加してくれるというマクロ

全体構成

.
├── .gitignore
├── hello-world-macro.xcworkspace
├── HelloWorld
│  ├── Sandbox
│  │  ├── Assets.xcassets
│  │  ├── Preview Content
│  │  └── SandboxApp.swift
│  └── Sandbox.xcodeproj
├── LICENSE
├── packages
│  ├── Package.swift
│  ├── Sources
│  │  ├── App
│  │  ├── Macros
│  │  └── Plugins
│  └── Tests
│     └── PluginTests
└── README.md

全体的なファイル構成はこんな感じになってます。
今回はアプリにマクロを組み込むという状況で設計しているので、
アプリ本体部とマクロ部に別れています。
また、プロジェクト自体はSwiftPMでパッケージ分離しています。
マクロを実装するのにSwiftPM経由でしか入れられないので、ちょうど良いですね。

HelloWorldフォルダ

アプリのmainファイルやその他構成ファイルを管理しているフォルダです。
今回の内容的にあんまり見るところはないと思います。

packagesフォルダ

アプリの実装を持っているSwiftPMで管理されるフォルダです。
Sourcesフォルダの中のフォルダ単位でSwiftPM上でPackage管理されます。

App Package

今回は一画面しか持たないので、アプリの画面としてはこのPackageだけがアプリのPackageとなっています。
作成したマクロを実際に適用する画面を持っているPackageになります。

Macros Package

実行ファイルとしてはマクロの定義ファイルのみのPackageになります。
Unit Testしたかったので、Testプランのファイルも入っています。

Plugin Package

マクロの実装部を格納するPackageです。
このリポジトリで一番重要なPackageになります。

マクロ実装内容

マクロ定義

今回は 自立型マクロ(Freestanding Macros) で作成しています。

https://github.com/MrSmart00/HelloWorldMacro/blob/eb45af6c3127978f0313afb7132e227a810096e1/packages/Sources/Macros/Difinitions.swift#L8-L9

@freestanding(expression) を指定することで自立型マクロとして定義できます。

マクロ実装

https://github.com/MrSmart00/HelloWorldMacro/blob/eb45af6c3127978f0313afb7132e227a810096e1/packages/Sources/Plugins/HelloWorld.swift#L11-L26

Plugin/HelloWorld.swiftの中で、実際の動作を実装しています。
引数で取得できた文字列の接頭辞に Hello World、接尾辞に !!! を追加するだけの簡単な内容です。

ユニットテスト

https://github.com/MrSmart00/HelloWorldMacro/blob/6bfb9dcf592f156f1c520c01448041148e3ebc44/packages/Package.swift#L36-L49

Package.swiftの構成上、Plugins Packageのテストとして PluginTests を設定しているんですが、Unit Test上ではPlugins Packageの参照ができずビルドエラーになってしまう状態で困っていたんですが、

https://forums.swift.org/t/cant-test-macros-on-xcode-15-1/69349/2

こちらのコメントでもあるように、マクロのテストは Mac を指定しないとダメなようです(大抵の場合 My Mac になるんですかね🤔)

まとめ

これで今回作成したリポジトリの説明は終わりです。
かなりシンプルな構成にしましたが、Swift Macros自体の扱いが結構難しいですね😅
次は付属型のマクロを作ってみようかと思っています🤔 👈作りました!!

https://zenn.dev/nexearth/articles/4fc745cf4ea32a

ぜひこっちもみてください🙏

Discussion