Meta Programming Swift with Sourcery

We all hate to copy and paste boring and repetitive boilerplate code. It happens in every project, iOS in particular. It appears in many places throughout our code base and it’s an indirect violation of the DRY principle. We all know that it’s a bad sign.

It’s an issue that doesn’t usually get enough attention. It involves getting out of our comfort zone, as generating code can be hard.

Fortunately, we have a solution to start automating boilerplate code in our Swift projects. I stumbled upon it while searching for a solution for our project at the office. It took me quite a while to get things going so I decided to layout a simple example to start with.

Let’s take a look at this example:

Now, we want to compare our Car struct in various places in our code. So we extend it to conform the Equatable protocol

While some might say: well it’s one method… 4 lines of code and a bit of copy paste. It’s really not that bad.

Think about that:

  • The Swift compiler won’t fail if you missed a variable while comparing.
  • Every time you add new properties you have to remember to revisit this method manually.
  • You could potentially have multiple boilerplate functions spreading across multiple amounts of files (Hashable, Description, Tests, Enum cases etc’).

Dealing with these cases will become a hassle, repetitive and most of all, dangerous. This is where all of the sneaky runtime bugs can easily appear.

Lets look at a better way of doing things

Meet Sourcery, by Krzysztof Zabłocki.

Sourcery scans your source code, applies your personal templates and generates Swift code for you, allowing you to use meta-programming techniques to save time and decrease potential mistakes.

While it might look a bit overwhelming, this amazing tool can make all of it happen automatically! We’ll go over the example above and automate it hoping it’ll ease you in and get you right down to business.

Sourcery is a binary tool. Lets look at it’s basic usage instructions:

$ ./sourcery <source> <templates> <output>
  • Source: a path to the folder containing source files we would like to use as our input ( Car.swift in our case).
  • Template: a path to the template file. We’ll build one in just a minute.
  • Output: Where the newly generated code will be created.

Templates are written with Stencil syntax and are not more then a simple Swift file mixed with Stencil tags to help us automate code creation.

Lets look at a simple Equatable template:

Equatable Template

1,11: We for-loop over all of the structs we supplied to Sourcery as an input, our Swift files. {% %} We’ll tell Stencil that we’re writing a command, for-loop in this case, and make sure to end it. Stencil will copy everything inside for each loop (text and code.)

2,3,6: These are made up of simple text lines mixed with {{variables}}. Stencil will print the variable value.

5,7: We’re going over each variable of the current type that we’re looping over and creating a comparison between the left and the right variable.

Running this template on our Car.swift file will auto generate the following:

It worked! Now we can start to implement custom templates for our project. This will save a lot of time and headache in the future. Sourcery gives you a much larger interface for your Swift source files than I’ve shown here. This will allow you to implement strong and flexible templates, so be sure to take a look at the documentation and see what’s available.

Tips and tricks

  • When writing the templates, you can run the Sourcery command with a watch argument:
    $ ./sourcery <source> <templates> <output> --watch
    This will allow you to see the results of your template each time you save.
  • You should consider adding Sourcery to your target build phases.

I’m available on Twitter if you’re interested in continuing the discussion.

If you found this article useful, I’d appreciate you clicking the 💚 below.