【Swift】SwiftLint(静的解析ツール)の導入と使い方!アプリの中身をチェック

【Swift】SwiftLint(静的解析ツール)の導入と使い方!アプリの中身をチェック

この記事からわかること

  • Swiftで使える静的解析ツールとは?
  • SwiftLint使い方
  • アプリ中身自動チェックする方法
  • .swiftlint.yml書き方
  • Fastlaneでの実行方法
  • Command PhaseScriptExecution failed with a nonzero exit codeの解決法

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

静的解析ツールとは?

静的解析ツール」とはプログラムが記法や規約に則って記述されているかを自動で解析するためのツールです。これを使用することでルールに準じていないコードを特定でき、修正箇所を簡単に識別できるようになります。

プログラムが一定のルールに則って記述されることで冗長なコードのリファクタリングによるコンパイル時間の短縮や可動性向上による複雑性の緩和と保守しやすいコードを保つことができます。

Android

SwiftLintとは?

公式リファレンス:SwiftLint

SwiftLintSwiftで使用できる静的解析ツールです。チェックできる項目は多く、インデントやスペース、変数の命名などなかなか人では気づきにくい部分もツールを使用することで簡単に識別することが可能です。

またSwiftLintではチェックするファイル自体や細かいルールもカスタマイズすることができるようになっています。

導入方法

SwiftLintHomebrewCocoa Podsを使用して導入することが可能です。

Homebrewでインストール

おすすめ記事:【Mac】Homebrewインストール方法!

HomebrewはMacOS(及びLinux)のパッケージ管理システムです。ターミナルからSwiftLintを使用するためにコマンドラインでXcodeが使用できるかを確認しておきます。以下コマンドでバージョンが返ってくるか試しておきます。

$ xcode-select --version
xcode-select version 2409.

問題なければSwiftLintをインストールします。

$ brew install swiftlint

Cocoa Podsでインストール

おすすめ記事:【Swift UI】CocoaPodsのインストール方法と使い方

Cocoa PodsはObjective-CまたはSwiftのライブラリ管理ツールです。インストール方法は他のライブラリと変わらず以下の文を「PodFile」に書き込んでpod installを実行するだけです。


pod 'SwiftLint'
$ pod install

静的解析の使い方と実行方法

SwiftLintを実行する方法はいくつかありますが、今回はXcode内からRun Scriptに組み込む形で実行させるようにしていきます。これでアプリをビルドした際に自動で実行されます。

おすすめ記事:【Swift/Xcode】Run Scriptの設定方法!ビルド時に処理を実行する

まずはXcodeから「TARGET」>「Build Phases」>「Run Script」をクリックします。もしなければ上部の「+」をクリックし「New Run Script Phase」で追加してください。

【Swift】SwiftLint(静的解析ツール)の導入と使い方!アプリの中身をチェック

追加できたらコードブロックの中に以下を書き込みます。swiftlintコマンドを実行することで静的解析が実行されるようになっています。そのためターミナルなどから実行したい場合はswiftlintを実行すればOKです。

【Swift】SwiftLint(静的解析ツール)の導入と使い方!アプリの中身をチェック

Homebrew

XcodeのRun Scriptに記述する際は/opt/homebrew/bin/swiftlintのように記述しないと期待通りに動作しませんでした。

if [ -f /opt/homebrew/bin/swiftlint ]; then
  /opt/homebrew/bin/swiftlint
else
  echo "⚠️⚠️⚠️ Warning: SwiftLintが未インストール⚠️⚠️⚠️"
fi

Cocoa Pods

if which "${PODS_ROOT}/SwiftLint/swiftlint" >/dev/null; then
    ${PODS_ROOT}/SwiftLint/swiftlint
else
    echo "⚠️⚠️⚠️ Warning: SwiftLintが未インストール⚠️⚠️⚠️"
fi

Based on dependency analysis」のチェックは外しておいてください。

あとはプロジェクトをビルド(Cmd + B)すれば自動でSwiftLintが働きコードをチェックしてくれます。すると以下のようにエラーや警告がたくさん表示されます。デフォルトのルールは結構厳しめなので良きルールに改変して使用してください。

【Swift】SwiftLint(静的解析ツール)の導入と使い方!アプリの中身をチェック

エラーや警告を自動修正する

SwiftLintを使用して出たエラーや警告の一部はSwiftLintの自動修正機能を使用することで解消することができる場合があります。コマンドで--fix --formatを実行すればインテントや冗長な初期値、isEmptyの使用などを自動でプロジェクト全体(※)を修正してくれます。

$ swiftlint --fix --format

※ 全体と記述しましたが後述している「.swiftlint.yml」でexcludedしているファイルは除外されます。

特定のファイルにのみ自動整形を実行したい場合はファイルパスを指定すればOKです。

$ swiftlint --fix --format {ファイルパス}

またフォーマッターとしてSwiftFormatというツールもあるので気になる方は以下を参考にしてください。

おすすめ記事:【Swift】SwiftFormatの導入と使い方!コードを自動で修正する

.swiftlint.yml:規約を設定する

SwiftLintのルールを設定するにはプロジェクトの直下に.swiftlint.ymlを作成し、適切なルールを記述しておく必要があります。細かいルールの構築方法は以下の公式サイトを確認してください。

公式リファレンス:SwiftLintCore Reference Rule Directory Reference

以下は公式に記載されていたサンプルをそのまま組み込んだところCommand PhaseScriptExecution failed with a nonzero exit codeというエラーが出たので少し修正し、コメント日本語にしたものです。


# デフォルトでは、SwiftLint は適切なデフォルトルールセットを使用します。以下で調整可能です。
disabled_rules: # デフォルトで有効になっているルールのうち、除外したいルールを指定
  - colon              # コロンのスタイルチェックを無効化
  - comma              # カンマのスタイルチェックを無効化
  - control_statement  # if などの制御文の書き方チェックを無効化

opt_in_rules: # デフォルトでは無効になっているルール。使用するには明示的に opt-in が必要
  - empty_count        # `.count == 0` の代わりに `.isEmpty` を使うことを推奨するルール
  # 利用可能なすべてのルールは `swiftlint rules` コマンドで確認できます

# 代わりに、使用するすべてのルールを明示的に指定する方法もあります(以下のオプションのコメントを外す)
# only_rules: # `disabled_rules` と `opt_in_rules` はこの設定を使う場合は削除してください
#   - empty_parameters
#   - vertical_whitespace

analyzer_rules: # `swiftlint analyze` 実行時に適用されるルール
  - explicit_self      # 明示的な self の使用を推奨

## 以下をコメントアウトしました
#included: # lint 対象とするパス(大文字小文字を区別)。これを指定すると `--path` は無視される
#  - Source

excluded: # lint の対象外とするパス(大文字小文字を区別)。`included` より優先されます
  - Carthage
  - Pods
  - Source/ExcludedFolder
  - Source/ExcludedFile.swift
  - Source/*/ExcludedFile.swift # ワイルドカードでファイルを除外

# true の場合、lint 対象ファイルが見つからなくても SwiftLint は失敗しません
allow_zero_lintable_files: false

# 設定可能なルールのカスタマイズ
# バイナリルールは severity(警告レベル)を設定できます
force_cast: warning # `as!` の強制キャストに対して警告

force_try:
  severity: warning # `try!` の強制使用に対して警告

# 警告とエラーのレベルを持つルールは、警告レベルのみを設定することも可能
line_length: 110 # 1行の最大文字数。これを超えると警告

# 警告とエラーの両方を設定する場合(配列で設定)
type_body_length:
  - 300 # 警告レベル
  - 400 # エラーレベル

# 警告とエラーを明示的に設定する場合
file_length:
  warning: 500  # ファイル行数が 500 行で警告
  error: 1200   # ファイル行数が 1200 行でエラー

# 命名規則ルールの設定:min/max 長さの警告・エラー閾値、除外対象など
type_name:
  min_length: 4 # 最小長さに対する警告
  max_length:
    warning: 40
    error: 50
  excluded: iPhone # 除外する型名
  allowed_symbols: ["_"] # 型名に許可される記号

identifier_name:
  min_length:
    error: 4 # 最小長さに満たない識別子に対してエラー
  excluded:
    - id
    - URL
    - GlobalAPIKey # 特定の識別子を除外

# エラー・警告の出力形式を指定(例: xcode, json, markdown など)
reporter: "xcode"

コード内の一部でルールを無効化する

全体には適用しているルールを特定のファイルやコードでのみ許容させたい場合に,ファイルやコード単位でルールを無効化することが可能です。無効化するためにはコードのファイル内にコメントする形で記述します。disableで無効化を始め、指定したルールのenableがある箇所まで無効化します。enableの記載がない場合はファイルの終わりまで適応されます。

// swiftlint:disable <rule1> [<rule2> <rule3> ...]
// ... 無効にしたいコード ...
// swiftlint:enable <rule1> [<rule2> <rule3> ...]

例えばline_lengthidentifier_nameを無視させる場合は以下のようになります。

// swiftlint:disable line_length identifier_name
let A = "短すぎる変数名かつ長すぎる文字列"
// swiftlint:enable line_length identifier_name

1行だけ無効したい場合はswiftlint:disable:thisswiftlint:disable:nextを使用します。thisならコードの行に、nextならコメントを記載した次のコードが無効化されます。

let value = value as! String // swiftlint:disable:this force_cast
// swiftlint:disable:next force_cast
let key = key as! String

Fastlaneを使用して実行する

公式リファレンス:SwiftLint - Fastlane

Fastlane経由でSwiftLintを使用できるようになっています。使い方は簡単でswiftlintアクションに適切な引数を渡すだけです。

swiftlint(
    mode: :lint,                            # SwiftLint の実行モード(:lint = 通常の検査, :autocorrect = 自動修正)
    # Homebrewでインストール済みならパス指定は不要
    executable: "Pods/SwiftLint/swiftlint", # SwiftLint 実行ファイルのパス(CocoaPods で導入した場合は必須)
    path: "/path/to/lint",                  # 検査対象のディレクトリパス(省略可能)
    output_file: "swiftlint.result.json",   # 出力結果を保存するファイルパス(省略可能)
    reporter: "json",                       # 出力形式(json, xcode, html, github-actions など)
    config_file: ".swiftlint-ci.yml",       # 使用する設定ファイルのパス(省略可能。デフォルトは .swiftlint.yml)
    files: [                                # 特定のファイルのみを検査したい場合に指定(省略可能)
        "AppDelegate.swift",
        "path/to/project/Model.swift"
    ],
    ignore_exit_status: true,               # SwiftLint がエラー終了しても fastlane を停止させない(デフォルト: false)
    quiet: true,                            # 'Linting 開始' や '完了' などのログ出力を抑制する(デフォルト: false)
    strict: true                            # 警告もエラーとして扱い、処理を失敗と見なす(デフォルト: false)
)

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

Search Box

Sponsor

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article