Swiftの静的解析を行うためにSwiftLintをインストールしてみた

[Tailorのインストール、実行を試してみた](http://qiita.com/ht40/items/e1bd5072f316f64c5480)ので[SwiftLint](https://github.com/realm/SwiftLint)も試してみる。

#インストール
[公式ページ](https://github.com/realm/SwiftLint)にのっているので省略。
Tailorとほぼ同じでHomebrewが入っていれば簡単。

#SwiftLintのチェックをXcodeビルド時に実行できるようにする
Tailorの時と同様にBuild Phaseにスクリプトを記載するとできる。
Build PhaseでNew Run Script Phase
スクリプト名を`SwiftLint`にして以下内容を記載。

#
    if which swiftlint >/dev/null; then
        swiftlint
    else
        echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
    fi

こんな感じになります。

![スクリーンショット 2017-07-05 15.46.19.png](https://qiita-image-store.s3.amazonaws.com/0/178502/15330d78-76bf-0ccd-6c15-4c0a9281af17.png)

Tailorとほぼ同じ手順。

#実行
設定できたはずなのでビルドしてみると・・・
無事動いたがワーニングだけでなくエラーも出ている。
※Tailorでは14このwarningだったソース

![スクリーンショット 2017-07-05 15.52.04.png](https://qiita-image-store.s3.amazonaws.com/0/178502/ec3d1972-0703-5f5d-e844-36be39df9386.png)

なんとなく優秀そうだぞ。と思って公式ページをみると90コほど[ルール](https://github.com/realm/SwiftLint/blob/master/Rules.md)があった。
ルールが多ければいいというわけではないが。
SwiftLintもTailor同様にymlファイルでルールの設定が細かくできるようだ。

#ルールの設定
こちらもTailorとほぼ同じ手順でOK。
xcodeprojectファイルと同階層に`.swiftlint.yml`を作成することで可能になる。
Tailorを試していたことで作業がかなり捗る。

`.swiftlint.yml`を作成せずにビルドするとこんな感じ。デフォルトのチェック状態
デフォルトの設定は以下コマンドで確認できる
#
    $ swiftlint rules

![スクリーンショット 2017-07-05 16.52.15.png](https://qiita-image-store.s3.amazonaws.com/0/178502/208ca8ce-1322-ecc6-e671-904a71715636.png)


デフォルトのコメントもエラーになっている。１行は120文字以内でないとエラーになっている。
このあたりを回避するために`.swiftlint.yml`を作成し以下の内容を記載。
#
    # 実行から除外するルール
    disabled_rules:
    # テストコード、Pod等のライブラリは対象外
    excluded:
    - Pods/
    - Podfile
    - Podfile.lock

    # 1行あたりの文字数制限
    line_length: 300

`line_length: 300`で１行あたりの文字数制限を緩和して再実行

![スクリーンショット 2017-07-05 16.57.27.png](https://qiita-image-store.s3.amazonaws.com/0/178502/96d61715-d082-7118-cb7c-d1339f684ee3.png)
こんな感じでエラーが消えた。

試しに残りの２つのワーニングも消してみる。
（本当にワーニングの必要はないかは別問題で実験）

#
    # 実行から除外するルール
    disabled_rules:
    - trailing_whitespace
    - vertical_whitespace
    - trailing_newline

    # テストコード、Pod等のライブラリは対象外
    excluded:
    - Pods/
    - Podfile
    - Podfile.lock

    # 1行あたりの文字数制限
    line_length: 300

ビルドしてみると無事ワーニングも消えた。

![スクリーンショット 2017-07-05 17.07.08.png](https://qiita-image-store.s3.amazonaws.com/0/178502/2dabd254-81ac-c759-87a3-e0645983d5cc.png)

こんな感じでソース内に記述することで一部のワーニング、エラーを除外することもできる

~~~swift
    func applicationWillResignActive(_ application: UIApplication) {
        // swiftlint:disable:next line_length
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
        // swiftlint:disable:previous line_length
    }
~~~

ポイントは対象を`// swiftlint:disable:next ルール`、`// swiftlint:disable:previous ルール`で対象を囲むこと。
今回は１行の文字数制限をルールから除外してみた。
#
        // swiftlint:disable:next line_length
        ****
        // swiftlint:disable:previous line_length


![スクリーンショット 2017-07-05 17.31.26.png](https://qiita-image-store.s3.amazonaws.com/0/178502/aea12679-a510-b553-bb5d-a4878034beee.png)

無事チェックされなくなったのでエラーが消えた。
ちなみに`// swiftlint:disable line_length`のように囲まずに１行だけ書くと記載箇所以降はルールが適用されなくなる。

#SwiftLintを触った感想
ルールの設定、数値など細かく設定できること、自前のルールも作成できるとのことなのでより細かくルールを決めたい場合はSwiftLintが良さそうだ。
使えそうな匂いがするのでルールについて確認してみる。

#ルールについて
独自にまとめようと思ったが素晴らしくまとまったものがあったのでこちらを参考に。
リンク先のサンプル通り、opt-in_rulesは記載しておいてコメントアウトすると使いやすいかな。

- [SwiftLintのRules全まとめ](http://qiita.com/kagemiku/items/80e6d905dc0059c342b3)
- [swiftlint 0.18.1 までの rule まとめ](http://qiita.com/rd0501/items/103c33d2df20f052523a)
- [swiftlint 最新版(0.18.1) の設定ファイル(.swiftlint.yml)のサンプル](http://qiita.com/rd0501/items/ceabe756c419ec082030#_reference-079b137ee3496b3e81ea)

.swiftlint.ymlで設定する項目。

```:.swiftlint.yml
    # 無効にするルール
    disabled_rules:
    - trailing_whitespace
    # デフォルト無効のルールのうち、有効にするルール
    opt_in_rules:
    - attributes
    # Lint対象に含めるファイルがあるパスを記述。
    included:
    - Source
    # Lint対象から外すファイルのあるパスを記述。includedより優先される。Podsやライブラリなど。
    excluded:
    - Pods/
    - Podfile
    # configurable rules can be customized from this configuration file
    # binary rules can set their severity level
    # 1行あたりの文字数制限
    line_length: 300
```
opt-in-rulesだけ抜き出してみた。
各ルールの説明は参考サイトの説明や公式ページの内容を機械的に翻訳して埋めてみた。
すでにまとめていただいているものはわかりやすいが、よくわからないものもある。
`extension_access_modifier`と`no_extension_access_modifier`は相反する推奨になっている？
除外するルールや、有効にするルールは随時見直していく。

```:.swiftlint.yml
　　opt_in_rules:
    - attributes                              # 属性は関数と型の独自の行にあるべき
    - closure_end_indentation                 # クロージャの最後の } は開始したラインと同じインデントを持つ必要がある
    - closure_spacing                         # クロージャ内の式はカッコの間に1つのスペースがあるべき
    - conditional_returns_on_newline          # 条件文は始まった行の次の行でreturnするべき．
    - empty_count                             # 要素が何もないことを確認する際はcount == 0よりもisEmptyを用いてチェックする
    - explicit_init                           # 明示的な.init()メソッドの呼び出しは避けるべき．
    - explicit_top_level_acl                  # 最上位の宣言では、アクセス制御レベルのキーワードを明示的に指定する必要がある
    - explicit_type_interface                 # クラス変数とかインスタンス変数とかには"型"を記述しろ
    - extension_access_modifier               # 拡張アクセス修飾子を使用することを推奨
    - fatal_error_message                     # fatalErrorを使う場合はメッセージを書く
    - file_header                             # ファイルの先頭のコメントの書式
    - first_where                             # .filter { }.firstよりも.first(where:)を用いる．
    - force_unwrappin                         # ! 使うな
    - implicit_return                         # クロージャの暗黙のリターンを推奨
    - implicitly_unwrapped_optional           # 暗黙的なUnwrapは禁止
    - multiline_parameters                    # 関数とメソッドのパラメータは、同じ行または1行に1つずつ指定する必要がある
    - nimble_operator                         # Nimble演算子のオーバーロードは、フリーマッチャー関数よりも優先
    - no_extension_access_modifier            # 拡張アクセス修飾子を使用しないことを推奨する                       
    - number_separator                        # 3桁ごとに _ 
    - object_literal                          # イニシャライザを直接呼び出すよりは#imageLiteralや#colorLiteralを用いる．
    - operator_usage_whitespace               # 演算子を使用する前後にスペース                      
    - overridden_super_call                   # メソッドを override したら super を呼ぶ
    - private_outlet                          # @IBOutlet は private に
    - prohibited_super_call                   # いくつかのメソッドにおいてはsuperを呼び出すべきではない．
    - redundant_nil_coalescin                 # nil結合演算子において，左辺がnilの場合のみ評価される性質上，右辺にnilを書くのは冗長なため，書くべきでない．
    - sorted_imports                          # import をアルファベット順に
    - switch_case_on_newline                  # switch文におけるcaseの各処理は改行した後書くべき
    - vertical_parameter_alignment_on_call    # 関数のパラメータは宣言の複数の行にある場合、垂直方向に整列させる必要がある
```

#参考
- [SwiftLint公式](https://github.com/realm/SwiftLint)
- [SwiftLint導入](http://qiita.com/syamaoka/items/2edfe315940d91846bf0)
- [SwiftLintを使ってみよう！](http://grandbig.github.io/blog/2016/02/13/swift-lint/)
- [SwiftLintの.swiftlint.yml記述方式とその詳細](http://qiita.com/akatsuki174/items/45205e0f0948f11e9db5)