GenerambaとSourceryでファイルとボイラープレートコードを自動生成する

やりたいこと

Viewを作るためのコードを作っていた際に、 下記のようなコードを繰り返し書くことがありました。

このようなボイラープレートコードを何度も書くのは面倒です。

自動でコードを生成する仕組みを使えないかと思い、自動生成するための処理を書いてみました。

public class SampleView: UIView {
    @IBOutlet private var nameLabel: UILabel!

    public var name: String? {
        get {
            nameLabel.text
        }
        set {
            nameLabel.text = newValue
            nameLabel.isHidden = newValue == nil 
        }
    }
}

完成物

GitHub - 46kuro/AtomicDesignSample

$ sh CreateTemplate.sh -n Sample -p name=String,name2=String

上記のようなCommand1つで、SampleViewというPublicなClassと、name, name2の2つのPropertyとIBOutletのProperty、空のXibファイルを生成することができました。

処理の流れ

  • Templateのファイルを生成する
  • Templateファイル内にPropertyに紐づくコードを生成する

全てを自前で実装することはとても難しいと思ったので、ライブラリに頼りつつ、上記処理を実装していきました。

Templateのファイルを生成する

ファイル生成ではxctemplateを使用する方法などもありますが、コマンドライン上からファイルをXcodeのReferenceに追加したかったので、Generambaを使用しました。

Generambaを使用し、下記のようなSwiftコードを生成していきます。

import UIKit

public class {{ module_info.name }}View: UIView {

    // sourcery:inline:{{ module_info.name }}View.TemplateName
    // sourcery:end

    override public func awakeFromNib() {
        super.awakeFromNib()
    }
}

Generambaを使用することで、Command上から法則性に沿ったSwiftファイルを作成することができました。

sourcery: のコメントは、次に説明するSourceryで生成されるコードを入れる範囲になります。

Templateファイル内にPropertyに紐づくコードを生成する

先ほど作成されたSwiftファイルに対し、Propertyに紐づくコードを生成していこうと思います。

コード生成のためにSouceryを使用しました。

Sourcery is a code generator for Swift language, built on top of Apple's own SourceKit. It extends the language abstractions to allow you to generate boilerplate code automatically.

メタプログラミングツールとして使われる、ボイラープレートコードを自動生成するためのツールです。

今回くらいの規模感であれば、Shellで書こうと思えば書けるような気もしますが、Sourceryの勉強のために使ってみました。

Sourceryを使ったコード生成の処理について1つずつ説明すると長くなりそうなので、別で記事を書こうと思います。

こちらのようなコードを生成することができました。

import UIKit

public class SampleView: UIView {

    // sourcery:inline:{{ module_info.name }}View.TemplateName    
    @IBOutlet private var nameLabel: UILabel!

    public var name: String? {
        get {
            nameLabel.text
        }
        set {
            nameLabel.text = newValue
            nameLabel.isHidden = newValue == nil 
        }
    }
    // sourcery:end

    override public func awakeFromNib() {
        super.awakeFromNib()
    }
}

最後に sed -i '' -e '/sourcery:/d' でsourcery関連のコメントを削除すれば、ボイラープレートコードをコマンド上で自動生成することができました。

参考

感想

GenerambaとSourceryを使用することで、コマンド1つでTemplateを作るところまでできました。

できたことはとりあえず良かったですが、依存しているツールも多くなってしまったので、もう少しシンプルな形にして実際にプロジェクトで使えると良いなと思います。

Souceryはいつか触ってみたいと思いつつ手が出せていなかったので、Stencilの文法やドキュメントの見方などを勉強する良い機会になりました。

メタプログラミングはとても面白いと思うので、Souceryを支えているSouceKitなどのFrameworkも勉強していきたいと思いました。

Generambaは、コマンドからSwiftファイルを生成するいい方法が他に分からなかったので、取り急ぎ使用しています。他に使いやすいツールがあれば、そういうものを使用したいです。

もしかしたら、Sourcery(SourceKitなどのツール)のみでSwiftファイルを生成する方がシンプルかもしれません。