# 静的解析ツールとは

静的解析ツールとは、ソースコードを解析して特定のルールに違反していないかチェックするための仕組みです。例えば、インデントの数や変数の命名規則、セミコロンの有無などの書き方を決めることによってプロジェクト内で統一したフォーマットを保つことができます。

静的解析ツールは、ツールによっては自動でコードのフォーマットを整えてくれる機能があるため、プログラマが意識しなくてもコードの可読性や保守性を向上してくれるメリットがあります。

# Swiftの静的解析ツール

Swiftの静的解析ツールやフォーマッターは次のようなものがあります。

次節で、SwiftLintとSwiftFormatの使い方を見ていきましょう。

# SwiftLintとは

SwiftLintはSwiftの静的解析ツールの一つで、コンパイラよりも詳細にソースコードの解析をすることができます。デフォルトでは、GitHubのスタイルガイド を元にコードを解析します。

# SwiftLintのインストール

SwiftLintは、ソースコードからのビルド、Homebrewや Mint からインストールすることができます。

今回は、パッケージ管理のしやすさからMint経由でインストールします。

# Mintのインストール

まずは、HomebrewでMintをインストールします。

brew install mint

# Mintfileの作成

Mintfileは、パッケージのリストを指定することができます。特定のリポジトリとバージョンが一元管理されるので、インストールと実行が簡単にできます。

プロジェクトのルートディレクトリでMintfileを作成し、次のように記述してください。

realm/SwiftLint@0.39.2

次のコマンドでインストールします。bootstrap はMintfileに含まれている全てのパッケージをインストールします。

mint bootstrap

インストールが終わったら、次のコマンドでバージョンを確認してみましょう。

mint run swiftlint version

0.39.2

TIP

min run パッケージ名 で指定したコマンドを実行することができますが、リンクはされていないので直接は呼び出せません。

swiftlint version

command not found: swiftlint

グローバル環境にインストールしたい場合は、--link オプションを指定すると /usr/local/bin にリンクされるのでコマンドを直接呼び出せます。

mint bootstrap --link
swiftlint version

# XCodeの設定

次に、XCodeでビルド時に静的解析を行うように設定してみましょう。

対象のプロジェクトから、Build Phases タブへ移動し、左上にある + をクリックしてください。

SwiftLint

+ をクリックしたら、New Run Script Phase を選んでください。

SwiftLint

Run Script の中で、次のようにコードを記述してください。

if which mint >/dev/null; then
  mint run swiftlint
else
  echo "warning: Mintがインストールされていません。こちらからダウンロードしてください https://github.com/yonaskolb/Mint"
fi

SwiftLint

上記のスクリプトは、ビルド時に自動で実行されて静的解析がされます。

# 差分のみ静的解析する

SwiftLintはデフォルトだとプロジェクト内の全てのファイルを解析するので大量の警告とエラーが出るかもしれません。また、それに伴いビルド時間も伸びる可能性があります。それを避けるために、次のようにgitの差分を見て変更があったファイルだけを解析すると、ビルド時間の短縮と警告の制御をすることができます。

if which mint >/dev/null; then
  git diff --name-only | grep .swift | while read filename; do
    mint run swiftlint  --path "$filename" 
  done
else
  echo "warning: Mintがインストールされていません。こちらからダウンロードしてください https://github.com/yonaskolb/Mint"
fi

# SwiftLintルールの設定

プロジェクトのルートディレクトリに .swiftlint.yml を作成すると詳細なルールを設定することができます。

公式サイト で設定について詳しく説明しているのでご確認ください。

例えば、あるフォルダを解析する対象から外したい場合は次のように書きます。

excluded:
  - Carthage
  - Pods

各ルールについては、SwiftLint Rules で確認することができます。

# SwiftFormatとは

SwiftFormat とは、コードのフォーマットをするためのコマンドラインツールです。インデントを調整したり、不要な括弧を削除したり、コードを解析して標準的なSwiftの書き方に修正してくれます。

SwiftFormatを使うことによって、プロジェクト内で共通のコードスタイルを保つことができます。

# SwiftLintとSwiftFormatの違い

SwiftLintでも、swiftlint autocorrect --format をすると自動でコードを修正してくれます。しかし、SwiftLintは静的解析を目的にしているので細かいスタイルの統一はできません。

一方、SwiftFormatは、コードのフォーマットを目的にしているのでルールを詳細に設定することができます。例えば、次のようなスタイルを統一するにはSwiftFormatが有効になります。

  • 暗黙的なselfを追加、または削除する
  • 括弧や式の前後に空白を挿入する
  • Import文をアルファベット順にする

# SwiftFormatのインストール

SwiftLint同様に、Mintでインストールします。

MintFileに次のコードを追加してください。

nicklockwood/SwiftFormat@0.44.13

次に、インストールします。

mint bootstrap

インストールされたら、バージョンを確認してみましょう。

mint run swiftformat --version

0.44.13

# Xcodeの設定

SwiftLintの設定方法と同様に、対象のプロジェクトから、Build Phases タブへ移動し、左上にある + をクリックして New Run Script Phase を選んでください。

SwiftLint

Run Scriptで次のようにコードを追加してください。gitの差分を見て、変更があったファイルのみフォーマットをかけています。

if which mint >/dev/null; then
  git diff --name-only | grep .swift | while read filename; do
    mint run swiftformat "$filename"
  done
else
  echo "warning: Mintがインストールされていません。こちらからダウンロードしてください https://github.com/yonaskolb/Mint"
fi

TIP

次のようなエラーが出た場合は、ルートディレクトリに .swift-version ファイルを作成し、使用しているSwiftのバージョンを記述しましょう。

No Swift version was specified, so some formatting features were disabled. Specify the version of Swift you are using with the --swiftversion command line option, or by adding a .swift-version file to your project.

.swift-version にSwiftのバージョンを記述する。

5.2.4

上記の設定で、ビルド時に自動的にコードのフォーマットがされるようになりました。

# SwiftFormatルール

SwiftFormatで適用されているルールは、swiftformat --rules で確認することができます。適用されていないルールは disabled が表示されます。

 mint run swiftformat --rules

 andOperator
 anyObjectProtocol
 blankLinesAroundMark
 blankLinesAtEndOfScope
 blankLinesAtStartOfScope
 blankLinesBetweenScopes
 braces
 consecutiveBlankLines
 consecutiveSpaces
 duplicateImports
 elseOnSameLine
 emptyBraces
 fileHeader
 hoistPatternLet
 indent
 isEmpty (disabled)
 leadingDelimiters
 linebreakAtEndOfFile
 linebreaks
 numberFormatting
 ranges (deprecated)
 redundantBackticks
 redundantBreak
 redundantExtensionACL
 redundantFileprivate
 redundantGet
 redundantInit
 redundantLet
 redundantLetError
 redundantNilInit
 redundantObjc
 redundantParens
 redundantPattern
 redundantRawValues
 redundantReturn
 redundantSelf
 redundantVoidReturnType
 semicolons
 sortedImports
 spaceAroundBraces
 spaceAroundBrackets
 spaceAroundComments
 spaceAroundGenerics
 spaceAroundOperators
 spaceAroundParens
 spaceInsideBraces
 spaceInsideBrackets
 spaceInsideComments
 spaceInsideGenerics
 spaceInsideParens
 specifiers
 strongOutlets
 strongifiedSelf
 todos
 trailingClosures
 trailingCommas
 trailingSpace
 typeSugar
 unusedArguments
 void
 wrap
 wrapArguments
 yodaConditions

# SwiftFormatルールの設定

ルートディレクトリに .swiftformat ファイルを作成すると詳細なルールやオプションを設定することができます。

例えば、--indent を設定すると インデントの数を指定できます。

--indent 4

指定したフォルダをフォーマット対象から外したい場合は、--exclude オプションを使用します。

--indent 4

--exclude Pods, Carthage

ルールを無効化したい場合は、--disable オプションを使用します。

--indent 4

--exclude Pods,Carthage

--disable trailingCommas,numberFormatting

各ルールの詳細は、公式サイトの Rules をご確認ください。