Edited at

ktlintを使いこなす 【kotlin】【lint】

More than 1 year has passed since last update.


ktlintとは

ktlintはkotlinの静的コード解析ツールです。

同じようなものに、detektというものもあります。

今回は、ktlintについて書いていきます。

ktlintはkotlinのコードにlintをかけるだけでなく、lintで検出した部分にフォーマットをかけることもできます。


使い方

ktlintの導入方法です。


gradleの場合

configurations {

ktlint
}

dependencies {
ktlint "com.github.shyiko:ktlint:$KTLINT_VERSION"
}

check.dependsOn ktlint


lintのtaskを追加

task ktlint(type: JavaExec, group: "kotlin verification") {

description = 'Check Kotlin code style.'
args 'src/**/*.kt'
main = 'com.github.shyiko.ktlint.Main'
classpath = configurations.ktlint + sourceSets.main.output
}

image.png

./gradlew ktlintでlintを走らせることができます。


formatのtaskを追加

task ktFormat(type: JavaExec, group: "kotlin Formatting") {

description = 'Fix Kotlin code style deviations.'
args '-F', 'src/**/*.kt'
main = 'com.github.shyiko.ktlint.Main'
classpath = configurations.ktlint + sourceSets.main.output
}

image.png

./gradlew ktFormatを使ってlintで検出された箇所にフォーマットをかけることができます。


CLIの場合

brewを使ってインストールできます。

brew install shyiko/ktlint/ktlint

ktlint "src/**/*.kt"


Output形式

ktlintでは様々なoutput形式を用意しています。

--reporterオプションを使ってOutputの形式を指定することができます。

task ktlint(type: JavaExec, dependsOn: classes) {

description = 'Check Kotlin code style.'
args 'src/**/*.kt', '--reporter=plain'
main = 'com.github.shyiko.ktlint.Main'
classpath = configurations.ktlint + sourceSets.main.output
}


--reporter=plain

デフォルトのアウトプット形式です。

takusemba/ktlint-sample/app/…/Hoge.kt:44:1: Unexpected blank line(s) before "}"

takusemba/ktlint-sample/app/…/Fuga.kt:108:1: Needless blank line(s)

takusemba/ktlint-sample/app/…/Foo.kt:25:7: Line break before assignment is not allowed

takusemba/ktlint-sample/app/…/Bar.kt:47:1: Unexpected blank line(s) before “}"


--reporter=checkstyle

xml形式でアウトプットすることもできます。

<?xml version="1.0" encoding="utf-8"?>

<checkstyle version=“8.0">
<file name="takusemba/ktlint-sample/app/…/Hoge.kt">
<error
line="25"
column="7"
severity="error"
message="Line break before assignment is not allowed"
source="no-line-break-before-assignment" />
</file>

</checkstyle>


--reporter=json

json形式でアウトプットすることもできます。

[

{
"file": "ktrule/src/main/java/com/takusemba/Hoge.kt",
"errors": [
{
"line": 3,
"column": 1,
"message": "Line break before assignment is not allowed",
"rule": "no-line-break-before-assignment"
},
{
"line": 5,
"column": 1,
"message": "Line break before assignment is not allowed",
"rule": "no-line-break-before-assignment"
}
]
}
]


--reporter=your-custom-output

カスタムのアウトプット形式で出力することもできます。

まずは、Repoterインターフェースを実装します。

class CustomReporter(private val out: PrintStream) : Reporter {

private val errors = ArrayList<LintError>()

override fun onLintError(
file: String,
err: LintError,
corrected: Boolean) {
errors.add(err)
}
override fun afterAll() {
out.println("hello custom reporter.")
out.println("found ${errors.size} errors.")
}
}

次に、ReporterProviderインターフェースを実装したものに、先程のCustomReporterを指定します。

class CustomReporterProvider : ReporterProvider {

override val id: String = "custom-ktlint-reporter"

override fun get(
out: PrintStream,
opt: Map<String, String>
): Reporter = CustomReporter(out)

}

最後にMETA-INF/services/com.github.shyiko.ktlint.core.RuleSetProviderにReporterProviderを登録します。


META-INF/services/com.github.shyiko.ktlint.core.RuleSetProvider

com.takusemba.CustomRuleSetProvider


最後に、jarを生成して、-Rオプションで指定します。


task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}

task ktlint(type: JavaExec, group: "kotlin verification") {
description = 'Check Kotlin code style.'
args 'src/**/*.kt' , '-R', 'path/to/hoge.jar'
main = 'com.github.shyiko.ktlint.Main'
classpath = configurations.ktlint + sourceSets.main.output
}

image.png


ルールの除外

Ktlintであるコードに対して特定のルールまたは、全てのルールを適応外にすることができます。


特定のルール(no-wildcard-imports)を除外

import package.* // ktlint-disable no-wildcard-imports


全てのルールを除外

import package.* // ktlint-disable

では、対象とするコード全てに対して特定のルールを除外するにはどうすればよいのでしょうか。

ktlintには、特定のルールを除外する方法はありません。

しかし、作者いわく、このアプローチは意図的らしいです。

理由はこちらを御覧ください。

https://github.com/shyiko/ktlint/issues/21

しかし、ワークアラウンドは用意されています、

ktlintは最初に.editorconfigのスタイル設定を読み込みに行くため、そこに独自のスタイルを明記しておけば、そのスタイルに従ってlintがかけられます。


.editorconfig

[*.{kt,kts}]

indent_size=2
continuation_indent_size=4
insert_final_newline=unset
max_line_length=off


最後に

今回は基本的はktlintの使い方を紹介しました。

Ktlintを使った独自ルールの追加方法については、こちらの記事を書きましたので、見てみてください。

https://qiita.com/takusemba/items/77e882cada7daf6f35ec