Help us understand the problem. What is going on with this article?

[Android] ktlint の導入と感想

More than 1 year has passed since last update.

これは ゆめみ Advent Calendar 2018 の5日目の投稿です。

いまさら感があるのですが、先日にとある Android プロジェクトへ ktlint を導入する機会があったので、その手順をここに残したいと思います。これから導入しようと考えられている方の参考になれば。

前提

  • Android Studio: 3.2.1
  • ktlint:0.29.0

ktlint とは

ktlint の README にも書いてありますが、kotlinlang.orgAndroid Kotlin Style Guide のスタイルガイドを元にコードスタイルのチェックをしてくれる Kotlin 用の Linter です。Gradle のタスクとしてコマンドラインで実行できるので、CI に組み込めたりします。
(追記:CI への組み込みについては GitHub のプルリクエストを Bitrise x Danger x ktlint で自動レビューする に書きました。)

導入

Gradle への導入方法は ktlint の README のとおりですが、例えば Android Studio で新規にプロジェクトを作成した直後の app/build.gradle に導入(プラグインを使わない方法での導入)すると次のようになります。

app/build.gradle
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "io.github.hkusu.myapplication"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

+ configurations {
+     ktlint
+ }

+ dependencies {
+     ktlint "com.github.shyiko:ktlint:0.29.0"
+ }

+ task ktlint(type: JavaExec, group: "verification") {
+     description = "Check Kotlin code style."
+     classpath = configurations.ktlint
+     main = "com.github.shyiko.ktlint.Main"
+     args "src/**/*.kt"
+ }
+ check.dependsOn ktlint

+ task ktlintFormat(type: JavaExec, group: "formatting") {
+     description = "Fix Kotlin code style deviations."
+     classpath = configurations.ktlint
+     main = "com.github.shyiko.ktlint.Main"
+     args "-F", "src/**/*.kt"
+ }

ktlint のオプションを変更する場合は上記の args のところを変更します。例えば出力をカラフルにする場合は、args "src/**/*.kt" の箇所を args "--color", "src/**/*.kt" とします。参考までに、私の最近のプロジェクトでは、次のようなタスクにしています。

task ktlint(type: JavaExec, group: "verification") {
    description = "Check Kotlin code style."
    classpath = configurations.ktlint
    main = "com.github.shyiko.ktlint.Main"
    args "--android", "--color", "--reporter=plain", "--reporter=checkstyle,output=${buildDir}/reports/ktlint-results.xml", "src/**/*.kt"
    ignoreExitValue true
}

--android --color オプションを追加してるのと、CI 用に checkstyle 形式での出力を追加&チェックにひっかかっても異常終了させない(ignoreExitValue true)ようにしています。もし手元での lint の実行と CI 上のものでオプションを分けたい場合は、タスクを分ければいいです。

またプロジェクトディレクトリの直下に .editorconfig ファイルを作成し、追加のルールを指定しておくと良いでしょう。これはファイル末尾に改行が入ってるかのチェックと、コード一行の文字数のチェックです。(ちなみに弊社では最大文字数が Android Studio のデフォルト値?の 100 だとなかなか辛いものがあるので 128 にしています。)

.editorconfig
[*.{kt,kts}]
insert_final_newline=true
max_line_length=128

Lint の実行

プロジェクトのルートディレクトリで $ ./gradlew ktlint を実行します。結果が出力されます。

スクリーンショット 2018-11-30 21.41.26.png

ちなみに $ ./gradlew ktlintFormat でコード修正までやってくれるようですが、個人的にはまだ使ってません。

Android Studio のコードスタイル

ktlint でチェックができるとはいえ、ある程度は Android Studio のコードスタイルで自動整形されり、フォーマット時に自動修正されるようにしておきたいものです。

ktlint の README を見ると、次のようにおすすめの設定方法が書いてあります。

スクリーンショット_2018-12-03_15_27_13.png
https://github.com/shyiko/ktlint から引用)

「Option #1」の方法は、コマンドライン版の ktlint(Gradle でなく curl で導入した ktlint)で実行でき、Android プロジェクトで実行すると、おすすめ設定が反映された下記の5ファイルが生成されます。

  • .idea/codeStyles/codeStyleConfig.xml
  • .idea/codeStyles/Project.xml
  • .idea/inspectionProfiles/profiles_settings.xml
  • .idea/inspectionProfiles/ktlint.xml
  • .idea/workspace.xml

「Option #2」の方法は、「#1」の設定を手動でやる方法です。

個人的には「#1」の方法で自動生成されるのはなんとなく気持ち悪いし、それだけの為にコマンドライン版の ktlint を導入するのも嫌なので、「#2」の方法で十分かなと思います。

Continuation indent について

これは改行時のインデントのスペース数なのですが、上記のおすすめ設定では通常のインデントと同じ 4 となっています(Android Stuio のデフォルトは 8)。個人的には改行時のインデントは 8 として通常のインデントと区別した方がよいと思うので 8 のままにしています。

もし 8 スペースで困るケースがあるなら、そもそも「Continuation indent」として扱うか否かを見直した方が良いというスタンスです。これは Android Studio のコードスタイルの設定で、下図のように各ケースについて制御できます。

スクリーンショット_2018-12-03_16_06_15.png

感想

ktlint の場合、Lint のルールを個別に ON/OFF できる機能はないんですよね(もし勘違いならすみません)。いままで ktlint を導入していなかったプロジェクトへ導入して Lint をかけると大量にエラーになるし、Lint のルールはプロジェクト毎に決めればいいんじゃないか、と初めは思ったりもしました。

が、今は、個別のルールを ON/OFF できない事が逆に良い、と思っています。プロジェクト毎に適用するルールの検討で悩まなくていいし、プロジェクト間でルールに差異が生まれないからです。ktlint でこう決まってるから有無をいわず粛々と対応するだけ、という状況は、ある意味 楽でいいな〜と感じています。

あと、仮に ktlint を導入しない場合でも、Kotlin でコードを書くなら 「Option #2」の方法でも説明されている「Kotlin style guide」の導入はしておくと良いかなと思います。せっかく Android Studio が標準で用意しているものなので。

スクリーンショット 2018-12-03 16.46.38.png

hkusu
Software Engineer @ Yumemi, Inc JavaScript / Android / Kotlin / AWS etc..
http://hkusu.github.io
yumemi
みんなが知ってるあのサービス、実はゆめみが作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。Twitterで情報配信中https://twitter.com/yumemiinc
http://www.yumemi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away