Swift lintを使ってみる
これ使ってみてーってswift lintと、それを紹介している勉強会の動画を渡されたけど、最後まで聞くことに耐えられなれなかった、、、
何度か目の再生停止で、原文当たった方が幸せじゃない?と気付いたので、ついでに自分なりにまとめておく。
ちなこれ
realm/SwiftLint: A tool to enforce Swift style and conventions.
なにそれ
lintってのは聞いたことはあった。文法解析して、なんかエラー出すやつ。それのswift版。らしい。
うまく設定することで、指定したルールに沿わない書き方を見つけるとエラーやワーニングとして騒いでくれるとのこと。全く余計なお世話 ありがたや。
チーム作業でコーディング規約を強制させたい場合にきっと便利。
セットアップ
Homebrewは気持ち悪いので使いません。
どうせ自分では使わないだろうしプロジェクトのgitにそのまま突っ込む。
cd <project_dir>
git submodule add https://github.com/realm/SwiftLint.git
するとディレクトリが作れられてくれるので、インストールしとく。途中で管理者権限を要求されます
cd swiftLint; make install
続いて、Xcode Projectに呼び出しを仕込む。
TargetのBuild Phaseを開いて、左上の「+」でNew Run Script Phaseを追加。エラー文をちょっと弄ってある。
if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed. To install, run 'cd <proj_dir>/swiftLint; make install'"
fi
lintなので、Compile Sourcesの次くらいに実行されるように
マウスドラッグで移動させておく。
cmd-bでビルドして、エラーとワーニングが山のように量産されてlint氏ね わーすごいやーってなったら成功。
設定ファイルを作る
設定ファイルはプロジェクトのディレクトリに.swiftlint.yml
を置いとけばいいらしい。
とりあえずPodsとSwiftLintを排除。
cd <project_dir>
vi .swiftlint.yml
# Swift Lint Rules
excluded: # excluded directory
- Pods
- SwiftLint
ちなみにコード中に特定記法のコメントを書くことでも操作できるらしいけど、どうせやらない。し、本来的にやるべきでもない。
// swiftlint:disable <rule>
// swiftlint:enable <rule>
let noWarning2 = NSNumber() as! Int // swiftlint:disable:this force_cast
設定を書いてく
ワーニング うぜええええええ!!!!
…となるので、順番に殺していく。
最後の(trailing_whitespace)
に注目。これがルール名らしい。
ルールについてはソース読んでね!という公式の投げっぷり
See the Source/SwiftLintFramework/Rules directory to see the currently implemented rules.
なので、もうなんとでもなーれ、って気持ちで眺めましょう。
// SwiftLint/Source/SwiftLintFramework/Rules/TrailingWhitespaceRule.swift
public func validateFile(file: File) -> [StyleViolation] {
return file.lines.filter {
$0.content.hasTrailingWhitespace()
}.map {
StyleViolation(ruleDescription: self.dynamicType.description,
severity: configuration.severity,
location: Location(file: file.path, line: $0.index))
}
}
なんだ、このクソ実装...
空行の場合は例外視とか普通つけるでしょ、、、なんで設定の余地ないの?
というような場合は disabled_rules: に書いてあげるとルールが無効になり、平和が訪れます。
disabled_rules:
trailing_whitespace #since has no option to treat empty line,,,
追記した後にもう一回cmd-bしてみると、ちゃんとワーニングが消えます。
よしよし。
あとは無意味に厳しい行数制限をテキトーに緩めたりとか
line_length: #max length of each line
warning: 200
error: 500
type_body_length: #max line num of class body
warning: 1000
error: 3000
と、いうように、まずはルールを殺戮し尽くすところから始めるべきらしい。です。
とりあえず、現状、こんな感じ。完全に個人的な主観です。
disabled_rules:
# vvv will never enable
- trailing_whitespace
- opening_brace
- closing_brace
- statement_position
- todo
- force_cast
- force_try
- file_length
- cyclomatic_complexity
# vvv may enable in someday
- return_arrow_whitespace
- control_statement
# vvv may enable in nearday
- legacy_constructor
- legacy_constant
- trailing_newline
#
カスタムルール
ここまでで標準のルールの残念さ加減に気付いた皆さんに嬉しいお知らせで、なにやらカスタムルールも定義できるらしいです。
正規表現を書いてあげると良いらしい。
例えば、こんな感じ。
classやfuncの宣言の間には1行空行を入れましょう、というやつ。
custom_rules:
spacer_line:
name: "Spacer Line"
regex: "(\}\n)([ \t]*)((public )|(private )|(internal )|(override ))*((class)|(func))"
message: "Need empty line between func or class"
severity: error
あとmatch_kinds
形態分析結果ので絞り込めるっぽいのだけど、どれがどんな要素として扱われるのかがナゾで使い物にならないのが残念。
(現時点では)気合の正規表現で無理やり誤魔化すしかなさそう。
感想
最初のエラーの数には呆れたけど、いらないのをガンガンとブラックリストに突っ込んで機能を絞り込めばそこそこ使えそう。
warning/errorがXcode上で扱えるので、ビルド遅くなる以外は良さそう。
コロンがどこにあろうと(読み易ければ)なんでもいいや、な自分としては、規約違反はwarning出すようにしといて、commit前にちょろっと整えるようにするくらいで使うと結構便利かもしれない。
なお、自分は{をifの次行に書くことは許さない教なので、そういったところは戦争・・・もとい、事前の話し合いが重要かと思います。
その他
すっげーたくさんエラー出てるなあ。でもコードに見覚えないなー、、、
と思ったらSwiftLintが自分自身のコードに対して評価してワーニングとエラー吐きまくってたの、すっごくロックだわね…