
こんにちは。
アドグローブ ソリューション第三事業部の濵(はま)です。
普段はAndroidアプリを開発しています。
今回の記事では、Ktlintと少しだけEditorConfigの話をさせていただきます。
- lintって?
- Ktlint
- なにはともあれKtlintを入れてみる
- だけれども従いたくないこともある
- EditorConfigの導入
- だけどまぁ、EditorConfigで設定できる項目は少ない
- 最後に
lintって?
lintとは、コンピュータプログラムなどのソースコードを読み込んで内容を分析し、問題点を指摘してくれる静的解析ツール。また、そのようなツールで解析を行うこと。ツールを指す場合は “linter” (リンター)と呼ぶこともある。
lintとは - 意味をわかりやすく - IT用語辞典 e-Words
すごく雑に言えばコーディング規約を守っているかチェックしてくれるツールです。
この辺は指摘する方もされる方も嫌なので、可能な限りはツールを活用したいものです。
Ktlint
Androidアプリの開発で使用する言語は主にKotlin1です。
Kotlin用のlinter、それがKtlintです。
pinterest.github.io
チェックするルールは、Kotlin公式の規約とAndroidのKotlin規約がベースになっています。
なにはともあれKtlintを入れてみる
今回はお試しとして新規でプロジェクトを作成し、Ktlintを導入してみます。
(その方が特に前提とかなく分かりやすいですしね)
Android StudioはDolphinを使用します。

app/build.gradleに以下を追記します。configurations {
ktlint
}
task ktlint(type: JavaExec, group: "verification") {
description = "Check Kotlin code style."
classpath = configurations.ktlint
mainClass.set("com.pinterest.ktlint.Main")
args "src/**/*.kt"
// see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information
}
check.dependsOn ktlint
dependencies {
ktlint("com.pinterest:ktlint:0.47.1")
}
これで導入は完了です。
横に表示される ▶︎ を押して実行してみましょう。

プロジェクトを作成してからコードをいじっていないので成功して欲しいですが...

プロジェクトのルートまで移動して以下コマンドです。
$ ./gradlew ktlint
すると...
kei: ~/Documents/android_project/Ktlint $ ./gradlew ktlint > Task :app:ktlint FAILED /Users/kei/Documents/android_project/Ktlint/app/src/androidTest/java/jp/co/adglobe/ktlint/ExampleInstrumentedTest.kt:1:1: File must end with a newline (\n) (final-newline) /Users/kei/Documents/android_project/Ktlint/app/src/androidTest/java/jp/co/adglobe/ktlint/ExampleInstrumentedTest.kt:3:1: Imports must be ordered in lexicographic order without any empty lines in-between with "java", "javax", "kotlin" and aliases in the end (import-ordering) /Users/kei/Documents/android_project/Ktlint/app/src/androidTest/java/jp/co/adglobe/ktlint/ExampleInstrumentedTest.kt:9:1: Wildcard import (cannot be auto-corrected) (no-wildcard-imports) /Users/kei/Documents/android_project/Ktlint/app/src/test/java/jp/co/adglobe/ktlint/ExampleUnitTest.kt:1:1: File must end with a newline (\n) (final-newline) /Users/kei/Documents/android_project/Ktlint/app/src/test/java/jp/co/adglobe/ktlint/ExampleUnitTest.kt:3:1: Imports must be ordered in lexicographic order without any empty lines in-between with "java", "javax", "kotlin" and aliases in the end (import-ordering) /Users/kei/Documents/android_project/Ktlint/app/src/test/java/jp/co/adglobe/ktlint/ExampleUnitTest.kt:5:1: Wildcard import (cannot be auto-corrected) (no-wildcard-imports) /Users/kei/Documents/android_project/Ktlint/app/src/main/java/jp/co/adglobe/ktlint/MainActivity.kt:1:1: File must end with a newline (\n) (final-newline) /Users/kei/Documents/android_project/Ktlint/app/src/main/java/jp/co/adglobe/ktlint/MainActivity.kt:3:1: Imports must be ordered in lexicographic order without any empty lines in-between with "java", "javax", "kotlin" and aliases in the end (import-ordering) FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:ktlint'. > Process 'command '/Applications/Android Studio_Dolphin.app/Contents/jre/Contents/Home/bin/java'' finished with non-zero exit value 1 * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 1s 1 actionable task: 1 executed
見てみるとファイルの最終行が空行でないとか
MainActivity.kt:1:1: File must end with a newline (\n) (final-newline)
ワイルドカードインポートを使っているよとか
ExampleUnitTest.kt:5:1: Wildcard import (cannot be auto-corrected) (no-wildcard-imports)
のようですね。直していきましょう。
全て直し終えたら再度実行し、
kei: ~/Documents/android_project/Ktlint $ ./gradlew ktlint BUILD SUCCESSFUL in 1s 1 actionable task: 1 executed
と成功すれば導入は完了です!
だけれども従いたくないこともある
Ktlintが教えてくれる違反の中には「いやいやそれは無視でいいよ」とか、
「それはここまで緩くしてくれよ」となるものがあるかもしれません。
(1行を何文字まで許容するとか...)
特に既にコードがある状態から導入すると違反が大量発生して嫌気が差すかもしれません。
なのでルールを変える方法を少し見てみましょう。
EditorConfigの導入
まず結果が分かりやすいよう、Ktlintが違反とする状態に戻します。
(具体的にはソースファイルの最終行を空行でなくし、以下の実行結果になるようにします)
kei: ~/Documents/android_project/Ktlint $ ./gradlew ktlint > Task :app:ktlint FAILED /Users/kei/Documents/android_project/Ktlint/app/src/androidTest/java/jp/co/adglobe/ktlint/ExampleInstrumentedTest.kt:1:1: File must end with a newline (\n) (final-newline) /Users/kei/Documents/android_project/Ktlint/app/src/test/java/jp/co/adglobe/ktlint/ExampleUnitTest.kt:1:1: File must end with a newline (\n) (final-newline) /Users/kei/Documents/android_project/Ktlint/app/src/main/java/jp/co/adglobe/ktlint/MainActivity.kt:1:1: File must end with a newline (\n) (final-newline) FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:ktlint'. > Process 'command '/Applications/Android Studio_Dolphin.app/Contents/jre/Contents/Home/bin/java'' finished with non-zero exit value 1 * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 1s 1 actionable task: 1 executed
そうしたら、.editorconfigファイルをプロジェクトの直下に作成します。

# コメントアウトは#です
root = true
# 拡張子が kt または kts のファイルで
[*.{kt, kts}]
# 最終行に空行を入れない
insert_final_newline = false
この状態で再度実行します。
設定が反映されていれば、コードは手を加えなくても成功します。
kei: ~/Documents/android_project/Ktlint $ ./gradlew ktlint BUILD SUCCESSFUL in 1s 1 actionable task: 1 executed
Ktlint(とAndroid Studio)はEditorConfigでの設定内容を見てくれるので、最終行に空行がないことが違反でなくなる(あると逆に違反になる)わけですね。
だけどまぁ、EditorConfigで設定できる項目は少ない
EditorConfig公式 をみると設定できる項目は少ないです。
しかしながらAndroid Studio(というかIntelliJ系)で独自の設定項目が用意されており、例えば以下の設定のようにものによってはKtlintにも有効に作用します。
# org.junit.Assert.* のワイルドカードインポートは許可する ij_kotlin_packages_to_use_import_on_demand = org.junit.Assert.* # ちなみに↓こんな風にコメントを入れるとタスクが失敗したりするので、コメントは行を分けた方が良いです indent_style = space # インデント方式
独自の設定項目は生憎探す時間がありませんでしたが、Android Studioで.editorconfigを編集する際に候補が表示されるのでなんとなくは設定できるかと思います。

最後に
いかがでしたでしょうか?
今回の記事では、KtlintとEditorConfigの話をさせていただきました。
便利なツールなので、みなさんも是非活用していただければ嬉しいです。
最後までお読みいただきありがとうございました!
現在アドグローブではエンジニアを含め、さまざまなポジションで一緒に働く仲間を募集しています。
詳細については下記からご確認ください。みなさまからのご応募お待ちしております。
-
Flutterなら
Dartだったり、Swiftでもできなくなかったりするらしいですが↩