SwiftLintを試してみた

最近業務で`ESLint`をいじっていて、そういえば`Swift`にも`Linter`ってあるのかなと思って調べたらあった。

https://github.com/realm/SwiftLint

`Realm`がつくっているんですね

# `Linter`とは

ざっくばらんにいえば**コードの品質チェックツール**みたいなもので、具体的には「１行における文字数が長すぎないか」「ネストが深すぎないか」みたいなことをチェックしてくれます。動的型言語（少なくとも`Javascript`）ではかなり使われるのではないかと思います。

またコードレビューにおいて書き方がコーディング規約に沿っていないかをレビュアーが目視するよりも、Linterにまかせてしまおうという考え方もあると思います

# 実行環境

- Xcode `7.0 (7A220)`
- SwiftLint `0.3.0`

# インストール

## `homebrew`を使う

```
brew install swiftlint
```

## ソースからビルドする

`SwiftLint`を`clone`してきて

```
git submodule update --init --recursive; make install
```

# セットアップ

`Build Phases`の`Run Script`にて、以下のスクリプトをコピペする(わかりづらかったら[README](https://github.com/realm/SwiftLint#usage)直接みてください！)

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

# Lintをかけてみる

インストール、セットアップが済んだら早速ビルドしてみましょう。
個人でリリースしているTwitter読み上げクライアントアプリ**[Twitilized](https://itunes.apple.com/jp/app/twitilized/id1042204784?mt=8)**のプロジェクトで試してみたのですが、こんな感じの警告やエラーが出るようになりました

<img width="1280" alt="スクリーンショット 2015-11-07 16.06.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/50827/2f44eb5a-4fa2-8c86-437c-c549fdeb2ef9.png">

↑「クラス内の行数は200行以内におさめるべきだけど423行になっています」と。

<img width="1280" alt="スクリーンショット 2015-11-07 16.07.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/50827/34f226da-9461-7742-b4da-ba91f1c5f6a1.png">

↑「１行の文字数は100字以内におさめるべきだけど285文字になっています」と。

厳しすぎる!!w
下のものに至っては、デフォルトで生成されるコメントだし・・・。
ということで、`SwiftLint`では「各チェック項目のパラメータのカスタマイズ」や「そもそもこのチェック項目はうちのプロジェクトでは適用しない」などの設定ができるので、それをやってみたいと思います

# 設定ファイル

プロジェクトのルートディレクトリに`.swiftlint.yml`というファイルをつくります。中身としては、以下のようなものになります

```yaml:.swiftlint.yml
disabled_rules: # 適用したくないチェック項目を記述
  - line_length
included: # Lint対象のファイルのあるパスを記述、通常はプロジェクト名になると思います
  - Twitilized
excluded: # Lint対象から外すファイルのあるパスを記述、CocoaPodsやCarthage
  - Pods
# パラメータ（ここではline_lengthの値）をカスタマイズする、warningを出す値でerrorは出なくなる
line_length: 360
# パラメータ（ここではtype_body_lengthの値）をカスタマイズする、最初の値がwarningで２つ目の値がerror
type_body_length:
  - 400 # warning
  - 500 # error
```

ということで`disabled_rules`に`line_length`を書いてあげて、`included`, `excluded`ともに正しく設定して保存し、再度ビルドしてみます。これでさきほどのエラーが消えるかなと思ってやってみると・・・とくに変わりなし。
色々やってみて、どうも設定ファイルが効いていないみたいだなと思って`issues`をみてみると、以下のようなissueがあった

https://github.com/realm/SwiftLint/issues/112

少なくとも自分が試したときだと、`homebrew`でインストールしたものだと正しく動かなかったので、ソースからインストールしなおすと、、、`.swiftlint.yml`が正しく反映されて、無事エラーも消えた!!

# チェック項目

基本的には[Githubのスタイルガイド](https://github.com/github/swift-style-guide)を参考にしているらしく、

```
swiftlint rules
```

で確認できます。以下そのまま貼っておきます

- Line Length (line_length): Enforce maximum line length
- Leading Whitespace (leading_whitespace): This rule checks that there's no leading whitespace in your file.
- Trailing Whitespace (trailing_whitespace): This rule checks whether you don't have any trailing whitespace.
- Returning Whitespace (return_arrow_whitespace): This rule checks whether you have 1 space before return arrow and return type. Newlines are also acceptable.
- Trailing Newline (trailing_newline): Files should have a single trailing newline.
- Operator Function Whitespace (operator_whitespace): Use a single whitespace around operators when defining them.
- Force Cast (force_cast): This rule checks whether you don't do force casts.
- File Line Length (file_length): Enforce maximum file length
- Todo (todo): This rule checks whether you removed all TODOs and FIXMEs.
- Colon (colon): This rule checks whether you associate the colon with the identifier.
- Type Name (type_name): Type name should only contain alphanumeric characters, start with an uppercase character and between 3 and 40 characters in length.
- Variable Name (variable_name): Variable name should only contain alphanumeric characters, start with a a lowercase character and be between 3 and 40 characters in length. In an exception to the above, variable names may start with a capital letter when they are declared static and immutable.
- Type body Length (type_body_length): Enforce maximum type body length
- Function Body Length (function_body_length): Enforce maximum function length
- Nesting (nesting): Types should be nested at most 1 level deep, and statements should be nested at most 5 levels deep.
- Control Statement (control_statement): if,for,while,do statements shouldn't wrap their conditionals in parentheses.
- Opening Brace Spacing (opening_brance): Check whether there is a space before opening brace and it is on the same line.
- Comma Spacing (comma): One space before and no after must be present next to any comma.
- Statement Position (statement_position): This rule checks whether statements are correctly positioned.