Slide 1

Slide 1 text

SwiftLintをもっと活⽤する Natsumi Oishi Rakuten Group, Inc.

Slide 2

Slide 2 text

2 • Natsumi Oishi • ラクマ iOS Engineer Who am I?

Slide 3

Slide 3 text

3

Slide 4

Slide 4 text

4 1. .swiftlint.yml を使い分ける 2. SwiftLintの実⾏時間を短くする 3. analyze を使う Environment • Xcode 13.2.1 • SwiftLint 0.46.2 Topics

Slide 5

Slide 5 text

5 .swiftlint.yml を使い分ける

Slide 6

Slide 6 text

6 プロダクトコードでの不具合を防ぐために⼊れたルールによって、テストコードが 書きにくくなる .swiftlint.yml を使い分ける テストが書きにくい 🥺 ⚠ force_unwrapping ❌ force_try

Slide 7

Slide 7 text

7 ProjectRoot ├ .swiftlint.yml ├ SampleProject ├ Hoge.swift └ Fuga.swift └ SampleProjectTests ├ HogeTest.swift └ FugaTest.swift .swiftlint.yml を使い分ける プロダクトとテストでルールを分ける .swiftlint.yml で設定したルールが全体に適⽤される

Slide 8

Slide 8 text

8 ProjectRoot ├ .swiftlint.yml ├ SampleProject ├ Hoge.swift └ Fuga.swift └ SampleProjectTests ├ HogeTest.swift ├ FugaTest.swift └ .swiftlint.yml .swiftlint.yml を使い分ける プロダクトとテストでルールを分ける .swiftlint.yml で設定したルールが全体に適⽤される SampleProjectTests/.swiftlint.yml で設定したルールが SampleProjectTests 配下に適⽤される

Slide 9

Slide 9 text

9 ProjectRoot ├ .swiftlint.yml ├ SampleProject ├ Hoge.swift └ Fuga.swift └ SampleProjectTests ├ HogeTest.swift ├ FugaTest.swift └ .swiftlint.yml .swiftlint.yml を使い分ける プロダクトとテストでルールを分ける ⚠ force_unwrapping ❌ force_try ❌ force_cast ✅ force_unwrapping ✅ force_try ❌ force_cast opt_in_rules: - force_unwrapping # force_try, force_castは有効 .swiftlint.yml disabled_rules: - force_unwrapping - force_try SampleProjectTests/.swiftlint.yml

Slide 10

Slide 10 text

10 親︓ .swiftlint.yml ⼦︓ SampleProjectTests/.swiftlint.yml .swiftlint.yml を使い分ける プロダクトとテストでルールを分ける • 親の設定が⼦にも反映する • 親と⼦の設定が競合した場合、⼦の設定が優先される

Slide 11

Slide 11 text

11 ディレクトリ内に親と⼦のymlファイルを配置して、 App Target > Build Phases > Run Script Phaseで `swiftlint` コマンドを実⾏する (オプションなどの追加をしなくても勝⼿に使い分けてくれる) .swiftlint.yml を使い分ける 実⾏⽅法 - Xcode

Slide 12

Slide 12 text

12 --config オプションで親⼦関係のすべてのymlファイルを指定する .swiftlint.yml を使い分ける 実⾏⽅法 – コマンドライン $ swiftlint \ --config .swiftlint.yml \ --config SampleProjectTests/.swiftlint.yml 優先順位の低い順(親→⼦の順) で指定する

Slide 13

Slide 13 text

13 SwiftLintの実⾏時間を短くする

Slide 14

Slide 14 text

14 ⾃動修正の後に静的解析を実⾏すると、実⾏時間がどうしても⻑くなりがち SwiftLintの実⾏時間を短くする 実⾏時間が⻑い 🤔 $ swiftlint --fix --format $ swiftlint

Slide 15

Slide 15 text

15 SwiftLintの実⾏時間を短くする 必要なコードにのみSwiftLintを実⾏する https://github.com/realm/SwiftLint/issues/413 #issuecomment-184077062 変更があるファイル名を抽出、 そのファイルだけを対象に SwiftLintを実⾏

Slide 16

Slide 16 text

16 SwiftLintの実⾏時間を短くする 必要なコードにのみSwiftLintを実⾏する # 全てのファイルに対してSwiftLintを実⾏する run_swiftlint_all() { swiftlint --fix --format swiftlint } # 指定したファイルに対してのみSwiftLintを実⾏する run_swiftlint() { local filename="${1}" if [[ "${filename##*.}" == "swift" ]]; then swiftlint --fix --format --path "${filename}" swiftlint --path "${filename}" fi }

Slide 17

Slide 17 text

17 SwiftLintの実⾏時間を短くする 必要なコードにのみSwiftLintを実⾏する # 変更があるファイルを抽出する diff_unstaged_files=`git diff --name-only` diff_staged_files=`git diff --cached --name-only` diff_files=`echo "${diff_unstaged_files}"; echo "${diff_staged_files}"` if [ "`echo ${diff_files} | grep ".swiftlint.yml"`" ]; then # .swiftlint.ymlに変更があればすべてのファイルに対してSwiftLintを実⾏する run_swiftlint_all else # 変更があるファイルにのみSwiftLintを実⾏する echo "${diff_files}" | while read filename; do run_swiftlint "${filename}” done fi

Slide 18

Slide 18 text

18 analyze を使う

Slide 19

Slide 19 text

19 • 型チェックされたAST (abstract syntax tree、抽象構⽂⽊) を使い、通常の静的解 析より⾼度な分析ができる • README.mdには ”experimental” と記述がある • .swiftlint.yml の analyzer_rules にanalyze⽤のルールを記述する analyze を使う analyze?

Slide 20

Slide 20 text

20 analyze を使う analyzer_rules? https://realm.github.io/SwiftLint/ unused_import.html

Slide 21

Slide 21 text

21 1. DerivedDataをクリーンする(差分ビルドは analyze コマンドでは動作しない) 2. xcodebuild コマンドでコンパイラログを取得する 3. コンパイラログのパスを渡して `swiftlint analyze` を実⾏ analyze を使う 実⾏⽅法

Slide 22

Slide 22 text

22 analyze を使う 実⾏⽅法 #!/bin/bash # https://github.com/realm/SwiftLint#analyze-experimental workspace=”YOURWORKSPACE.xcworkspace" scheme=”YOURSCHEME" logfile="xcodebuild.log" # 1. DerivedDataをクリーンする xcodebuild clean \ -workspace ${workspace} \ -scheme ${scheme} # 2. コンパイラログを取得する xcodebuild build \ -workspace ${workspace} \ -scheme ${scheme} > ${logfile} # 3.コンパイラログのパスを渡して `swiftlint analyze` を実⾏ swiftlint analyze \ --compiler-log-path ${logfile} \ --fix exit 0 run_analyze.sh

Slide 23

Slide 23 text

23 • 実⾏時間が⾮常に⻑い • analyzer_rules がまだ4つしかなく、絶対に有効にしたいルールが無い analyze を使う イマイチなところ 🤔 • capture_variable • explicit_self • unused_declaration • unused_import

Slide 24

Slide 24 text

24 1. .swiftlint.yml を使い分ける 2. SwiftLintの実⾏時間を短くする 3. analyze を使う まとめ

Slide 25

Slide 25 text

No content