kotlinとLintとEditorConfig

チーム内で個人のkotlinの技術成熟度は小鳥から大鳥[^1]までプロジェクトで様々だと思います。自由度に合わせたコーディングルールが必要となるkotlinでの開発において、Lintがないのはやはり辛いですね。Lintを開発していただいてる世界中のエンジニアに感謝しつつ楽しみにしています。みなさんのプロジェクトではどんなルールがあり、それらをどう共通しているのでしょうか。

## Android Lintとkotlin

残念ながら僕は参加してないのですが、先日の[kotlinConf](https://www.kotlinconf.com/)でLintに関するセッションがありました。

<img width="1440" alt="スクリーンショット 2017-12-09 23.08.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/26883/d956f2e1-5d62-bb21-170a-23e1bbf7ec41.png">


- [動画](https://www.youtube.com/watch?v=p8yX5-lPS6o)
- [スライド](https://docs.google.com/presentation/d/1Sr-6E3Tk1lBguUob0GigqSEsfN-04qS56Whj0UEr0AE/edit#slide=id.g2a71b5cba6_0_53)

今後はコードをkotlinに置き換えつつ、より強力なサポートを追加してAndroid Lint2.0としていくそうです。しかし、現状ではAndroidLintはkotlinファイルの静的解析をIDEの機能からでしか行えません。

<img width="522" alt="スクリーンショット 2017-12-09 23.22.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/26883/43a74bb0-7f0e-1f8f-2537-95fe1b22e8d7.png">

これは[issue](https://developer.android.com/studio/preview/kotlin-issues.html)としてあげられています。
> **Lint checks with Kotlin don't work from command line**
Lint checks on Kotlin files only work from the Android Studio IDE. The currently do not run when you run lint directly from Gradle.

そのため、CIなどでいい感じに自動化できないです。これでは忘れてしまったり面倒でやらなかったりしてしまうのが世の常です。上記の発表でも告知されていますが、AndroidStudio3.1からサポートされ、`gradle`コマンドからLintをかければkotlinの静的解析が可能になります。

## ktlint

AS3.1以降の安定したLintの提供はもう少し時間がかかりそうなので、何か別な手段でLintを行おうと調べていくと以下のような記事を見つけます。

[コードレビューbotにKotlinコードのスタイルをチェックさせる](https://qiita.com/kafumi/items/1a9f59d6f845808604df)

上の素晴らしい記事に触発されたので僕もプロジェクトに[ktlint](https://github.com/shyiko/ktlint)入れるぞ :muscle: と、DangerやらAndroid Lintやらを準備していたら思わぬところに躓きました。ktlintではkotlinの公式Style Guideをベースにしていて、フォーマットに関する内容も含んでいてます。

例えばインデントに関して、[kotlin Code Conversations](https://kotlinlang.org/docs/reference/coding-conventions.html#coding-conventions)では次のようにあります。

> Naming Style
> - use 4 space indentation

また、[kotlin guide](https://android.github.io/kotlin-guides/style.html#indentation)でも

> Each time a new block or block-like construct is opened, the indent increases **by four spaces**. When the block ends, the indent returns to the previous indent level. The indent level applies to both code and comments throughout the block.

となっているため、インデントをスペース2つにしていると開発に嬉しくないワーニングが大量に出てしまうのでした…

:thinking: 。。。oO (it depends...

<img width="840" alt="スクリーンショット 2017-12-09 23.18.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/26883/b118fe1f-9954-85d2-5f48-a8c0debc5f58.png">

プロジェクトや個人の好みに応じて変化しやすい部分をLintに含めないでもらいたいというのが僕の主張ですが、

> Kotlin linter in spirit of feross/standard (JavaScript) and gofmt (Go).

とのことなのでフォーマッターらしい部分も持っているようです。なので導入する前に相談してみました。

<img width="788" alt="スクリーンショット 2017-12-09 5.34.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/26883/3b87a8ab-8c9d-637f-ad5d-4cbfc77abab0.png">

インデントに限らず、kotlinで記述するときはチームによって異なる部分はたくさんあると思います。他にも、

- dataクラスにする基準は何か
- importのフォーマットはどうするか
- companion objectの位置はどうするか（[ktlintでも議論されたようです](https://github.com/shyiko/ktlint/issues/63)）
- 改行はどこでするか

など、こういった細かなことを口伝していく開発は大変なので、可能なものはバシッとLintで解決していきたいのですが、そのktlintは簡単にカスタマイズできそうにありませんでした。
これでは:pray:公式頼む:pray:と待ち続けるしかない…

一瞬頭をよぎったのは面白そうな[detekt](https://github.com/arturbosch/detekt)を使ってみてCustomLintを作るか？！ということでしたが、自分たちのルールを決めるたびにを書いていくのはやや骨が折れそうです。(というか僕がいなくなったら誰もメンテしないなと)

_ちなみにAndroidLintの場合、`build.gradle`に`lintOption`を指定できるので、そこで無視したいLintを記述できたりします。他にもwarningは表示しないなども可能です。_

```build.gradle
lintOptions {
    disable 'YourDisableCase',~~
    ignoreWarnings true
}
```

## EditorConfig

万策尽きた〜と思っていたら、[ktlintの0.11.0](https://github.com/shyiko/ktlint/releases/tag/0.11.0)[^2]から[EditorConfig](http://editorconfig.org/)のルールを読み込むようになったのをつい最近知りました笑
EditorConfigはIDEで一貫したコーディングスタイルを定義しておけるもので、現在のAndroidStudioではプラグインなどの導入なしに設定可能です。

なので、上のインデントでのワーニングは `.editorconfig` ファイルを追加するだけで回避できるようになりました。

```:.editorconfig
[*.{kt,kts}]
indent_size=2
```

他にも[プロパティ](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties)は色々あるのでチェックしてみてください。

---

以上で今回つまずいたポイントは簡単に解決できたわけですが、Lintで解決できないルールもあると思うので、おすすめの解決方法あればコメントなどいただけると嬉しいです。

[^1]: 学術上では大きさによる分類はないそうな
[^2]: ちょうど議論していた頃にリリースされていたので、もうすこしちゃんとチェックしていればよかっただけですね…