Article
Introduction to SwiftPoet
July 2, 2018
SwiftPoet is a powerful framework built by Gilt Tech to let you generate your own Swift code… using Swift!
Why do this? Sometimes the job of a developer is to crank out some boilerplate code. It’s not all brilliant problem solving. Developers are great at recognizing patterns, and if it’s possible to automate something, we’ll do it.
I’m using SwiftPoet in a command line tool to translate Avro schema definitions into Swift structs that are customized to my liking. (To make your own — check out my article on how to setup a Swift Command Line Tool with a dependency .)
For reference, there is an API doc , but it doesn’t show you how to get started. I aim to rectify that in this article.
The goal is to generate a String
Ultimately we want to generate some Swift code. SwiftPoet provides that to us in String
form.
To do that, create a PoetFile
object and retrieve the generated Swift through the fileContents
property:
Not very exciting so far. To make it do anything interesting we need to give the PoetFile
some PoetSpecs
.
A PoetSpec
is used to represent every bit of Swift you can think of.
Want to generate a struct
? Check out StructSpec.
How about a field
? They got you withFieldSpec
. A parameter
is what you’re asking for? Use ParameterSpec
. (I hope you see the pattern.)
Here’s the thing, you can’t use them directly.
Builder pattern
There aren’t any public initializers for the specs! Try going StructSpec()
(it won’t work).
Instead, each spec has a static builder
method that returns a corresponding <type>Builder
for you to use. E.g. StructSpec.builder(for: “MyStruct")
returns a StructSpecBuilder
.
You then call the various add
methods on the StructSpecBuilder
to give it whatever characteristics you want, say, a field
!
This is where it gets a bit… verbose. To add a field
, you need to create a builder first and then build it.
As you can see, when you add a field
to a struct
or class
, you get it added to the default initializer method for free!
The other key thing to learn is TypeName
. This is where you park your type data. You can create one manually with TypeName(keyword: "MyType")
but they also provide a bunch of static values for common primitives.
CodeBlocks
CodeBlocks
let you manually specify what the code will look like. To make your life easier, SwiftPoet provides you with a handy extension on String
called .toCodeBlock()
.
Let’s add a method to our struct:
Swift’s multi-line string syntax really comes in handy when you’re writing code that writes code!
Final Example
Let’s bring it all together by adding a parameter to our method and providing some default values.
Note — we need to make our field
a var
to simultaneously give it a default value and allow it to be set in our initializer. Can you figure out how I changed it from let
to var
?
That should be enough to get you started! Hit me up @regularberry if you need any additional help.
Thanks a ton to the Gilt team for open sourcing this project!
Sean tries to automate himself out of a job at Livefront .-
Sean Berry
Software Engineer